(function (context, $) {

  "use strict";

  context.JK = context.JK || {};
  context.JK.ConfigureTracksDialog = function (app) {
    var logger = context.JK.logger;
    var ASSIGNMENT = context.JK.ASSIGNMENT;
    var VOICE_CHAT = context.JK.VOICE_CHAT;
    var gearUtils = context.JK.GearUtils;
    var sessionUtils = context.JK.SessionUtils;

    var $dialog                       = null;
    var $instructions                 = null;
    var $musicAudioTab                = null;
    var $musicAudioTabSelector        = null;
    var $voiceChatTab                 = null;
    var $voiceChatTabSelector         = null;
    var $certifiedAudioProfile        = null;
    var $btnCancel                    = null;
    var $btnAddNewGear                = null;
    var $btnUpdateTrackSettings       = null;
    var $btnCloseJamBlasterConfig     = null;

    var configureTracksHelper = null;
    var voiceChatHelper = null;
    var profiles = null;
    var currentProfile = null;
    var enableVstTimeout = null;


    var configure_audio_instructions = {
      "Win32": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " +
        "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " +
        "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " +
        "Gear button to test that device.",

      "MacOSX": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " +
        "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " +
        "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " +
        "Gear button to test that device.",

      "Unix": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " +
        "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " +
        "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " +
        "Gear button to test that device."
    };

    var configure_voice_instructions = "If you are using a microphone to capture your instrumental or vocal audio, you can simply use that mic " +
      "for both music and chat. Otherwise, choose a device to use for voice chat, and use arrow buttons to " +
      "select an input on that device.";

    function setInstructions(type) {
      if (type === 'audio') {
        $instructions.html("Click the 'ADD LIVE TRACK' button to add more tracks.  You may set up a live track for each instrumental and/or vocal part to perform in sessions. You must also set up exactly two Session Audio Output ports to deliver the stereo audio in your sessions.")
        return;
        var os = context.jamClient.GetOSAsString();
        $instructions.html(configure_audio_instructions[os]);
      }
      else if (type === 'voice') {
        $instructions.html(configure_voice_instructions);
      }
      else {
        throw "unknown type in setInstructions(" + type + ')';
      }
    }

    function activateTab(type) {
      if (type === 'voice') {
        $musicAudioTab.hide();
        $voiceChatTab.show();

        $musicAudioTabSelector.removeClass('selected');
        $voiceChatTabSelector.addClass('selected');
      }
      else {
        $musicAudioTab.show();
        $voiceChatTab.hide();

        $musicAudioTabSelector.addClass('selected');
        $voiceChatTabSelector.removeClass('selected');
      }
    }

    function validateVoiceChatSettings() {
      //return voiceChatHelper.trySave(); // not necessary since we use saveImmediate now
      return true;
    }

    function showMusicAudioPanel() {
      setInstructions('audio');
      activateTab('audio');
    }

    function validateAudioSettings() {
      return true;
    }

    function showVoiceChatPanel() {
      setInstructions('voice');
      activateTab('voice');
    }

    function events() {
      $musicAudioTabSelector.click(function () {
        // validate voice chat settings
        if (validateVoiceChatSettings()) {
          window.ConfigureTracksActions.reset(false);
          voiceChatHelper.reset();
          showMusicAudioPanel();
        }
      });

      $voiceChatTabSelector.click(function () {
        // validate audio settings
        if (validateAudioSettings()) {
          logger.debug("initializing voice chat helper")
          window.ConfigureTracksActions.reset(false);
          voiceChatHelper.reset();
          showVoiceChatPanel();
        }
        else {
          logger.debug("invalid audio settings; ignoring")
        }
      });

      $btnCancel.click(function() {
        app.layout.cancelDialog('configure-tracks');
        return false;
      });

      $btnAddNewGear.click(function() {

        app.layout.showDialog("add-new-audio-gear")
        return false;
      });

      $btnUpdateTrackSettings.click(function() {
        if(voiceChatHelper.trySave()) {
          app.layout.closeDialog('configure-tracks');
        }

        return false;
      });

      $certifiedAudioProfile.change(deviceChanged);
    }

    function renderCertifiedGearDropdown() {
      var optionsHtml = '';
      context._.each(profiles, function (profile) {
        if(profile.good) {
          optionsHtml += '<option title="' + profile.id + '" value="' + profile.id + '"' + (profile.current ? 'selected="selected"' : '') + '>' + profile.id + '</option>';
        }
      });
      $certifiedAudioProfile.html(optionsHtml);

      //context.JK.dropdown($certifiedAudioProfile);
    }

    function deviceChanged() {
      var profile = $certifiedAudioProfile.val();

      if(currentProfile == profile) {
        return; // just bail early, because the easydropdown fires change events even when you select the same value
      }
      logger.debug("activating audio profile: " + profile);

      var result = context.jamClient.FTUELoadAudioConfiguration(profile);

      if(!result) {
        logger.error("unable to activate audio configuration: " + profile + ", " + JSON.stringify(result));
        context.JK.alertSupportedNeeded("Unable to activate audio configuration for profile named: " + profile);
        renderCertifiedGearDropdown(); // force the dropdown to be reflective of the actually active profile
        return;
      }

      // FTUELoadAudioConfiguration eventually sets this, but apparently asynchronously
      result = context.jamClient.SetLastUsedProfileName(profile);

      if(!result) {
        logger.error("unable to activate audio configuration after loading it: " + profile);
        context.JK.alertSupportedNeeded("Unable to activate audio configuration for profile named: " + profile);
        return;
      }

      currentProfile = profile;

      window.ConfigureTracksActions.reset(false);
    }

    function beforeShow() {

      profiles = gearUtils.getProfiles();
      renderCertifiedGearDropdown();
      showMusicAudioPanel();

      currentProfile = context.jamClient.LastUsedProfileName();

      if(currentProfile != $certifiedAudioProfile.val()) {
        logger.error("the currently active profile (" + currentProfile + ") is not the same as the Certified Audio Gear dropdown (" + $certifiedAudioProfile.val() + ")");
        context.JK.alertSupportedNeeded("Unable to determine the current profile.");
      }

      var result = context.jamClient.FTUELoadAudioConfiguration(currentProfile);

      if(!result) {
        logger.error("unable to activate audio configuration: " + currentProfile + ", " + JSON.stringify(result));
        context.JK.alertSupportedNeeded("Unable to activate audio configuration for profile named: " + currentProfile);
        return;
      }

      window.ConfigureTracksActions.reset(false);
      if(!window.SessionStore.inSession()) {
        delayEnableVst()
      }
      else {
        logger.debug("in a session, so no delayEnableVst()");
      }
      voiceChatHelper.reset();
      voiceChatHelper.beforeShow();
    }

    function delayEnableVst() {
      if (enableVstTimeout) {
        clearTimeout(enableVstTimeout)
      }
      var isVstLoaded = context.jamClient.IsVstLoaded()
      var hasVstAssignment = context.jamClient.hasVstAssignment()

      if (hasVstAssignment && !isVstLoaded) {
        enableVstTimeout = setTimeout(function() { enableVst() }, 1000)
      }
    }

    function enableVst () {
      enableVstTimeout = null

      if (app.layout.isDialogShowing('configure-tracks')) {
        ConfigureTracksActions.enableVst()
      }
      else {
        logger.debug("no longer in configure tracks dialog; not enabling VSTs at this time")
      }
    }

    function afterShow() {

      if (!window.JamBlasterStore.pairedJamBlaster) {
        sessionUtils.SessionPageEnter();
      }

      if(currentProfile == 'JB Remote' || currentProfile == 'JamBlaster') {
        window.JamBlasterActions.resyncBonjour()
      }

      //context.ConfigureTracksActions.vstScan();

    }

    function onCancel() {
      return voiceChatHelper.cancel();
    }

    function afterHide() {
      voiceChatHelper.beforeHide();
      if(!window.JamBlasterStore.pairedJamBlaster) {
        sessionUtils.SessionPageLeave();
      }
    }

    function initialize() {

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

      app.bindDialog('configure-tracks', dialogBindings);

      $dialog = $('#configure-tracks-dialog');
      $instructions = $dialog.find('.instructions span');
      $musicAudioTab = $dialog.find('div[data-tab-id="music-audio"]');
      $musicAudioTabSelector = $dialog.find('.tab-configure-audio');
      $voiceChatTab = $dialog.find('div[data-tab-id="voice-chat"]');
      $voiceChatTabSelector = $dialog.find('.tab-configure-voice');
      $certifiedAudioProfile = $dialog.find('.certified-audio-profile');
      $btnCancel = $dialog.find('.btn-cancel');
      $btnAddNewGear = $dialog.find('.btn-add-new-audio-gear');
      $btnUpdateTrackSettings = $dialog.find('.btn-update-settings');

      //configureTracksHelper = new context.JK.ConfigureTracksHelper(app);
      //configureTracksHelper.initialize($dialog);

      voiceChatHelper = new context.JK.VoiceChatHelper(app);
      voiceChatHelper.initialize($dialog, 'configure_track_dialog', true, {vuType: "vertical", lightCount: 10, lightWidth: 3, lightHeight: 17}, 191);

      events();
    }

    this.initialize = initialize;

    return this;
  };

})(window, jQuery);