(function (context, $) {

  "use strict";

  context.JK = context.JK || {};
  context.JK.GearWizard = function (app) {

    var logger = context.JK.logger;
    var sessionUtils = context.JK.SessionUtils;

    var $dialog = null;
    var wizard = null;
    var $wizardSteps = null;
    var $templateSteps = null;
    var loopbackWizard = null;
    var adjustGearSettings = null;
    var inputs = null;

    var self = this;

    var STEP_INTRO = 0;
    var STEP_SELECT_DEVICE = 1;
    var STEP_SELECT_TRACKS = 2;
    var STEP_SELECT_CHAT = 3;
    var STEP_DIRECT_MONITOR = 4;
    var STEP_VIDEO_GEAR = 5;
    var STEP_ROUTER_NETWORK = 6;
    var STEP_SUCCESS = 7;

    var stepUnderstandGear      = new context.JK.StepUnderstandGear(app, this);
    var stepSelectGear          = new context.JK.StepSelectGear(app, this);
    var stepConfigureTracks     = new context.JK.StepConfigureTracks(app, this);
    var stepConfigureVoiceChat  = new context.JK.StepConfigureVoiceChat(app, this);
    var stepDirectMonitoring    = new context.JK.StepDirectMonitoring(app, this);
    var stepVideoGear           = new context.JK.StepVideoGear(app, this);
    var stepNetworkTest         = new context.JK.StepNetworkTest(app, this);
    var stepSuccess             = new context.JK.StepSuccess(app, this);

    var STEPS = {
      0: stepUnderstandGear,
      1: stepSelectGear,
      2: stepConfigureTracks,
      3: stepConfigureVoiceChat,
      4: stepDirectMonitoring      
    }

    function newSession() {
      inputs = null;

      context._.each(STEPS, function(stepInfo, stepNumber) {
        if(stepInfo.newSession) {
          stepInfo.newSession.call(stepInfo);
        }
      });
    }

    function onStepChanged(e, data) {
      var step = wizard.getCurrentStep();
      var $currentWizardStep = wizard.getCurrentWizardStep();

      // update ftue step numbers
      var $ftueSteps = $(context._.template($templateSteps.html(), {}, { variable: 'data' }));
      var $activeStep = $ftueSteps.find('.ftue-stepnumber[data-step-number="' + step + '"]');
      $activeStep.addClass('.active');
      $activeStep.next().show(); // show the .ftue-step-title
      $currentWizardStep.find('.ftuesteps').replaceWith($ftueSteps);
    }

    // checks if we already have a profile called 'FTUE...'; if not, create one.  if so, re-use it.
    function createFTUEProfile() {
      var profileName = context.jamClient.FTUEGetMusicProfileName();

      logger.debug("current profile name: " + profileName);

      if(profileName && profileName.indexOf('FTUE') == 0) {
        // remove junk
        context.jamClient.TrackDeleteProfile(profileName);
      }

      var newProfileName = 'FTUEAttempt-' + new Date().getTime().toString();
      logger.debug("setting FTUE-prefixed profile name to: " + newProfileName);
      context.jamClient.FTUESetMusicProfileName(newProfileName);
      if(context.jamClient.FTUESetPreferredMixerSampleRate) {
        context.jamClient.FTUESetPreferredMixerSampleRate(1);
        context.jamClient.FTUESetPreferredOutputSampleRate(1);
        context.jamClient.FTUESetPreferredChatSampleRate(1);
      }

      context.jamClient.FTUEClearChannelAssignments();
      newSession();

      var profileName = context.jamClient.FTUEGetMusicProfileName();

      logger.debug("name on exit: " + profileName);

    }

    function beforeShow(args) {
      //context.jamClient.FTUECancel();
      context.jamClient.FTUESetStatus(false);
      createFTUEProfile();
      sessionUtils.FTUEPageEnter();

      wizard.onBeforeShow(args);
    }

    function afterShow() {
      if(window.olark) olark('api.box.show');
    }

    function afterHide() {
      if(window.olark) olark('api.box.hide');
      wizard.onAfterHide();

      context.jamClient.FTUESetStatus(true);
      context.jamClient.FTUECancel();
      sessionUtils.FTUEPageLeave();
    }


    function reportFailureAnalytics() {
      // on cancel, see if the user is leaving without having passed the audio test; if so, report it
      var lastAnalytics = stepSelectGear.getLastAudioTestFailAnalytics();
      if(lastAnalytics) {
        logger.debug("reporting audio test failed")
        context.JK.GA.trackAudioTestFailure(lastAnalytics.platform, lastAnalytics.reason, lastAnalytics.data);
      }
      else {
        logger.debug("audiotest failure: nothing to report");
      }

      var lastAnalytics = stepNetworkTest.getLastNetworkFailAnalytics();
      if(lastAnalytics) {
        logger.debug("reporting network test failed");
        context.JK.GA.trackNetworkTestFailure(lastAnalytics.reason, lastAnalytics.data);
      }
      else {
        logger.debug("network test failure: nothing to report");
      }
    }

    function onCanceled() {
      reportFailureAnalytics();

      if (app.cancelFtue) {
        app.cancelFtue();
        app.afterFtue = null;
        app.cancelFtue = null;
      }

      return closeDialog();
    }

    function onClosed() {
      reportFailureAnalytics();

      if (app.afterFtue) {
        // If there's a function to invoke, invoke it.
        app.afterFtue();
        app.afterFtue = null;
        app.cancelFtue = null;
      }

      return closeDialog();
    }

    function closeDialog() {
      wizard.onCloseDialog();
      app.layout.closeDialog('gear-wizard');
      return false;
    }

    function events() {
      $(wizard).on('step_changed', onStepChanged);
      $(wizard).on('wizard_cancel', onCanceled);
      $(wizard).on('wizard_close', onClosed);
    }

    function setNextState(enabled) {
      wizard.setNextState(enabled);
    }

    function setBackState(enabled) {
      wizard.setBackState(enabled);
    }

    function moveToNext() {
      wizard.moveToNext();
    }

    function setChosenInputs(_inputs) {
      inputs = _inputs;
    }

    function getChosenInputs() {
      return inputs;
    }

    function initialize(_loopbackWizard, _adjustGearSettings) {

      loopbackWizard = _loopbackWizard;
      adjustGearSettings = _adjustGearSettings;

      // on initial page load, we are not in the FTUE. so cancel the FTUE and call FTUESetStatus(true) if needed
      if(context.jamClient.FTUEGetStatus() == false) {
        context.jamClient.FTUESetStatus(true);
      }
      //context.jamClient.FTUECancel();

      var dialogBindings = { beforeShow: beforeShow, afterShow: afterShow, afterHide: afterHide };

      app.bindDialog('gear-wizard', dialogBindings);

      $dialog = $('#gear-wizard-dialog');
      $wizardSteps = $dialog.find('.wizard-step');
      $templateSteps = $('#template-ftuesteps');
      var videoGear = $wizardSteps.filter($('.video-gear'))
      var networkTest = $wizardSteps.filter($('.network-test'))
      wizard = new context.JK.Wizard(app);


      var operatingSystem = context.JK.GetOSAsString();
      stepUnderstandGear.initialize($wizardSteps.filter($('[layout-wizard-step=0]')), self, operatingSystem);
      stepSelectGear.initialize($wizardSteps.filter($('[layout-wizard-step=1]')), self, operatingSystem);
      stepConfigureTracks.initialize($wizardSteps.filter($('[layout-wizard-step=2]')), self, operatingSystem);
      stepConfigureVoiceChat.initialize($wizardSteps.filter($('[layout-wizard-step=3]')), self, operatingSystem);
      stepDirectMonitoring.initialize($wizardSteps.filter($('[layout-wizard-step=4]')), self, operatingSystem);
      stepSuccess.initialize($wizardSteps.filter($('.success')), self);

      var dynamicStepCount = 5
      if(videoGear.length) {
        stepVideoGear.initialize(videoGear, self);
        STEPS[dynamicStepCount++] = stepVideoGear
      }

      if(networkTest.length) {
        // skip network test always
        //stepNetworkTest.initialize($wizardSteps.filter($('.network-test')), self);
        //STEPS[dynamicStepCount++] = stepNetworkTest
      }

      STEPS[dynamicStepCount++]=stepSuccess

      wizard.initialize($dialog, $wizardSteps, STEPS);
      events();
    }

    this.setChosenInputs = setChosenInputs; // so step 2 can 'talk' to step 3
    this.getChosenInputs = getChosenInputs;
    this.setNextState = setNextState;
    this.setBackState = setBackState;
    this.moveToNext = moveToNext;
    this.initialize = initialize;
    this.createFTUEProfile = createFTUEProfile;
    this.getWizard = function() {return wizard; }
    this.getLoopbackWizard = function() { return loopbackWizard; };
    this.getAdjustGearSettings = function() { return adjustGearSettings; };

    self = this;
    return this;
  };

})(window, jQuery);