/**
 * Common utility functions.
 */
(function (context, $) {

  "use strict";

  context.JK = context.JK || {};
  var sessionUtils = {};
  var rest = new context.JK.Rest();
  context.JK.SessionUtils = sessionUtils;
  var logger = context.JK.logger;
  var autoOpenJamTrack = null;

  var LATENCY = sessionUtils.LATENCY = {
    ME : {description: "ME", style: "latency-me", min: -1, max: -1},
    GOOD : {description: "GOOD", style: "latency-good", min: 0.0, max: 40.0},
    MEDIUM : {description: "FAIR", style: "latency-fair", min: 40.0, max: 70.0},
    POOR : {description: "POOR", style: "latency-poor", min: 70.0, max: 100},
    UNACCEPTABLE: {description: "UNACCEPTABLE", style: "latency-unacceptable", min: 100, max: 10000000},
    UNKNOWN: {description: "UNKNOWN", style: "latency-unknown", min: -2, max: -2}
  };

  sessionUtils.setAutoOpenJamTrack = function(jamTrack) {
    logger.debug("setting auto-load jamtrack", jamTrack)
    autoOpenJamTrack = jamTrack;
  }

  // one shot!
  sessionUtils.grabAutoOpenJamTrack = function() {
    var jamTrack = autoOpenJamTrack;
    autoOpenJamTrack = null;
    logger.debug("grabbing auto-load jamtrack", jamTrack)
    return jamTrack;
  }

  sessionUtils.createOpenSlot = function($openSlotsTemplate, slot, openSlotCount, currentSlotIndex) {
    var inst = context.JK.getInstrumentIcon24(slot.instrument_id);

    var proficiency_desc = slot.proficiency_desc;
    if(!proficiency_desc) {
      // this is to allow unstructured RSVPs to not specify proficiency_desc
      proficiency_desc = "Any Skill Level";
    }

    var moreLinkHtml = '';
    if (openSlotCount > 3 && currentSlotIndex === 2) {
      moreLinkHtml = '<a class="slots more">more</a><a class="details-arrow arrow-down-orange"></a>';
    }

    var slot = {
      instrument_url: inst,
      instrument: slot.description,
      proficiency: proficiency_desc,
      more_link: moreLinkHtml
    };

    return context.JK.fillTemplate($openSlotsTemplate.html(), slot);
  }

  sessionUtils.defaultTimezone = function($timezoneList) {
    var tz = jstz.determine().name();
    // first check if we have this particular timezone
    var found = null;
    if(tz) {
      found = $timezoneList.find('option[data-tz="' + tz +'"]')
    }

    if(found.length == 0 ) {
      // this is best effort path; it means some reason we couldn't match a timezone by jstz to our dropdown
      var offset = new Date().getTimezoneOffset() * 60; // convert to seconds to match data-utc-offset (seconds)
      found = $timezoneList.find('option[data-utc-offset="' + offset + '"]')
    }

    if(found.length > 0) {
      var defaultValue = found.attr('value');
      $timezoneList.easyDropDown('select', defaultValue).val(defaultValue);
    }
  }

  sessionUtils.scoreInfo = function(full_score, isSameUser) {
    var latencyDescription;
    var latencyStyle;
    var iconName;
    var description;

    if(isSameUser) {
      latencyDescription = LATENCY.ME.description;
      latencyStyle = LATENCY.ME.style;
      iconName = 'purple';
      description = 'me';
    }
    else if (!full_score) {
      latencyDescription = LATENCY.UNKNOWN.description;
      latencyStyle = LATENCY.UNKNOWN.style;
      iconName = 'purple';
      description = 'missing';
    }
    else if (full_score <= LATENCY.GOOD.max) {
      latencyDescription = LATENCY.GOOD.description;
      latencyStyle = LATENCY.GOOD.style;
      iconName = 'green';
      description = 'good';
    }
    else if (full_score <= LATENCY.MEDIUM.max) {
      latencyDescription = LATENCY.MEDIUM.description;
      latencyStyle = LATENCY.MEDIUM.style;
      iconName = 'yellow';
      description = 'fair';
    }
    else if (full_score <= LATENCY.POOR.max) {
      latencyDescription = LATENCY.POOR.description;
      latencyStyle = LATENCY.POOR.style;
      iconName = 'red';
      description = 'poor';
    }
    else {
      latencyStyle = LATENCY.UNACCEPTABLE.style;
      latencyDescription = LATENCY.UNACCEPTABLE.description;
      iconName = 'blue';
      description = 'unacceptable';
    }

    return {
      latency_style: latencyStyle,
      latency_text: latencyDescription,
      icon_name: iconName,
      description: description
    };
  }
  sessionUtils.createLatency = function(user) {
    return sessionUtils.scoreInfo(user.full_score, user.id === context.JK.currentUserId)
  }

  function clearAudioTimeout() {
    if(context.JK.AudioStopTimeout) {
      clearTimeout(context.JK.AudioStopTimeout);
      context.JK.AudioStopTimeout = null;
    }
  }

  sessionUtils.ensureValidClient = function(app, gearUtils, successCallback) {

    if(!context.JK.guardAgainstBrowser(app)) {
      return false;
    }

    if (!context.JK.JamServer.connected) {
      app.notifyAlert("Not Connected", 'To create or join a session, you must be connected to the server.');
      return false;
    }

    gearUtils.guardAgainstInvalidConfiguration(app)
      .fail(function() {
        app.notify(
          { title: "Unable to Join Session",
            text: "You can only join a session once you have working audio gear and a tested internet connection."
          });
      })
      .done(function() {
        if (successCallback) {
          successCallback();
        }
      });

  }

  sessionUtils.joinSession = function(sessionId) {

    var hasInvitation = false;
    var session = null;
    // we need to do a real-time check of the session in case the settings have
    // changed while the user was sitting on the Find Session screen
    rest.getSession(sessionId)
      .done(function(response) {
        session = response;
        if(session && session.recording) {
          context.JK.app.notify( { title: "Unable to Join Session", text: "The session is currently recording." }, null, true);
          return;
        }

        if (session) {
          if (session.can_join) {
            logger.debug("Found invitation or approved RSVP for user " + context.JK.currentUserId + ", session " + sessionId);
            openJoinSessionTerms(sessionId);
          }
          else {
            if(session.user_id == JK.currentUserId) {
              openJoinSessionTerms(sessionId);
            }
            else if (session.musician_access) {
              if (session.approval_required) {
                openJoinRequestAlert(sessionId);
              }
              else {
                openJoinSessionTerms(sessionId);
              }
            }
            else {
              // if it's private, yet we can see it, presumably we are friends (better there was a front-end check here)
              openJoinRequestAlert(sessionId);
            }
          }
        }
      })
      .fail(function(xhr, textStatus, errorMessage) {
        logger.debug("xhr.status = " + xhr.status);
        if (xhr.status === 404) {
          sessionNotJoinableAlert();
        }
        else {
          context.JK.app.notify(
            {   title: "Unable to Join Session",
                text: "There was an unexpected error while attempting to join the session."
            },
            null,
            true);
        }
      });
  }

  function openJoinRequestAlert(sessionId) {
    var alertDialog = new context.JK.AlertDialog(context.JK.app, "YES",
      "You must be approved to join this session. Would you like to send a request to join?",
      sessionId, onCreateJoinRequest);

    alertDialog.initialize();
    context.JK.app.layout.showDialog('alert');
  }

  function sessionNotJoinableAlert() {
    var alertDialog = new context.JK.AlertDialog(context.JK.app, "OK",
      "This session is over or is no longer public and cannot be joined. Please click Refresh to update the session list.",
      null,
      function(evt) {
        context.JK.app.layout.closeDialog('alert');
      }
    );

    alertDialog.initialize();
    context.JK.app.layout.showDialog('alert');
  }

  sessionUtils.tbdScheduledSessionWarning = function(callback) {
    var alertDialog = new context.JK.AlertDialog(context.JK.app, "OK",
      "If you start this session now, the scheduled start time will be set to the current date and time.",
      null,
      callback
    );

    alertDialog.initialize();
    context.JK.app.layout.showDialog('alert');
  }

  function openJoinSessionTerms(sessionId) {
    var termsDialog = new context.JK.TermsDialog(context.JK.app, sessionId, onJoinSessionTermsAccepted);
    termsDialog.initialize();
    context.JK.app.layout.showDialog('terms');
  }

  function onJoinSessionTermsAccepted(sessionId) {
    context.location = '/client#/session/' + sessionId;
  }

  function onCreateJoinRequest(sessionId) {
    var joinRequest = {};
    joinRequest.music_session = sessionId;
    joinRequest.user = context.JK.currentUserId;
    rest.createJoinRequest(joinRequest)
      .done(function(response) {

      }).error(function(jqXHR, textStatus, errorMessage) {
          var joinErr = jqXHR.responseJSON['errors']
          if (joinErr && joinErr['user_id'] == 'has already been taken') {
              context.JK.app.notify({title: "Oops!", 
                                     text: 'You have already requested to join this session.', 
                                     "icon_url": "/assets/content/icon_alert_big.png"});
          } else {
              context.JK.app.ajaxError(jqXHR, textStatus, errorMessage);
          }
      });

    context.JK.app.layout.closeDialog('alert');
  }

  sessionUtils.FTUEPageEnter = function() {
    logger.debug("sessionUtils: FTUEPageEnter");
    clearAudioTimeout();
    context.jamClient.FTUEPageEnter();
  }

  sessionUtils.FTUEPageLeave = function() {
    logger.debug("sessionUtils: FTUEPageLeave");
    clearAudioTimeout();
    context.jamClient.FTUEPageLeave();
  }

  sessionUtils.SessionPageEnter = function() {
    logger.debug("sessionUtils: SessionPageEnter");
    clearAudioTimeout();
    return context.jamClient.SessionPageEnter();
  }

  sessionUtils.SessionPageLeave = function() {
    logger.debug("sessionUtils: SessionPageLeave");
    clearAudioTimeout();
    context.jamClient.SessionPageLeave();
  }

})(window, jQuery);