(function (context, $) {

  "use strict";
  context.JK = context.JK || {};
  context.JK.RecordingFinishedDialog = function (app) {
    var logger = context.JK.logger;
    var rest = context.JK.Rest();
    var playbackControls = null;
    var recording = null; // deferred object
    var $dialog = null;

    function resetForm() {
      // remove all display errors
      $('#recording-finished-dialog form .error-text').remove()
      $('#recording-finished-dialog form .error').removeClass("error")
      removeGoogleLoginErrors()
    }

    function beforeShow() {
      $dialog.data('result', null);
      if (recording == null) {
        alert("recording data should not be null");
        app.layout.closeDialog('recordingFinished');
        return false;
      }

      resetForm();

      var parentSelector = '#recording-finished-dialog div.genre-selector';
      context.JK.GenreSelectorHelper.render(parentSelector);

      // preset genre from 1st genre in current session
      var currentOrLastSession = JK.CurrentSessionModel.getCurrentOrLastSession();
      if (currentOrLastSession && currentOrLastSession.genres.length > 0) {
        var genreDescription = currentOrLastSession.genres[0];
        context.JK.GenreSelectorHelper.setSelectedGenres(parentSelector, [genreDescription]);
      }

      var localResults = context.jamClient.GetLocalRecordingState({recordings: [recording]});

      if (localResults['error']) {
        logger.error("unable to open recording due to error: %o", localResults);
        app.notify({
          title: "Unable to Open Recording for Playback",
          text: localResults['error'],
          icon_url: "/assets/content/icon_alert_big.png"
        });
      }
      else {
        var localResult = localResults.recordings[0];
        if (localResult.aggregate_state == 'MISSING') {
          logger.error("unable to open recording due to all missing tracks: %o", localResults);
          app.notify({
            title: "Unable to Open Recording for Playback",
            text: "All of your tracks associated with the recording are missing. This is a bug in the application.",
            icon_url: "/assets/content/icon_alert_big.png"
          });
        }
        else if (localResult.aggregate_state == 'PARTIALLY_MISSING') {
          logger.error("unable to open recording due to some missing tracks: %o", localResults);
          app.notify({
            title: "Unable to Open Recording for Playback",
            text: "Some of your tracks associated with the recording are missing. This is a bug in the application.",
            icon_url: "/assets/content/icon_alert_big.png"
          })
        }
        else {

          // load recording
          var openRecordingResult = context.jamClient.PreviewRecording(recording);

          logger.debug("OpenRecording response: %o", openRecordingResult);

          if (openRecordingResult.error) {
            app.notify({
              "title": "Can't Open Recording",
              "text": openRecordingResult.error,
              "icon_url": "/assets/content/icon_alert_big.png"
            });
          }
          else {
            // hunt for missing backing tracks; if so, mark them as silent
            context._.each(openRecordingResult.backing_tracks, function(backingTrack) {
              if(backingTrack.local_state == "MISSING") {
                // mark this as deleted
                logger.debug("marking recorded track as deleted")
                rest.markRecordedBackingTrackSilent({recording_id: openRecordingResult.recording_id, backing_track_id: backingTrack.client_track_id})
                  .fail(function() {
                    app.notify({
                      "title": "Unable to Mark Backing Track",
                      "text": "A backing track was never played, but we could not tell the server to remove it from the recording.",
                      "icon_url": "/assets/content/icon_alert_big.png"
                    });
                  })
              }
            })
          }

          playbackControls.startMonitor();
        }
      }

    }

    function afterHide() {
      recording = null;
      playbackControls.stopMonitor();
      context.jamClient.ClosePreviewRecording();
    }

    function onCancel() {
      return false;
    }

    function discardRecording(e) {

      resetForm();
      registerDiscardRecordingHandlers(false);

      rest.discardRecording({
        id: recording.id
      })
        .done(function () {
          logger.debug("recording discarded by user. recordingId=%o", recording.id);
        })
        .fail(function (jqXHR) {
          logger.error("recording discard by user failed. recordingId=%o. reason: %o", recording.id, jqXHR.responseText);
        })
        .always(function () {
          $dialog.data('result', {keep:false});
          app.layout.closeDialog('recordingFinished')
          registerDiscardRecordingHandlers(true);
        })
      return false;
    }

    function startGoogleLogin(e) {
      e.preventDefault()
      logger.debug("Starting google login")
      window._oauth_win = window.open("/auth/google_login", "Log In to Google", "height=500,width=500,menubar=no,resizable=no,status=no");
      
      window._oauth_callback = function() {
        window._oauth_win.close()
        setGoogleAuthState()
      }
      return false;
    }

    function claimRecording(e) {
      resetForm();
      registerClaimRecordingHandlers(false)

      var upload_to_youtube = $('#recording-finished-dialog form input[name=upload_to_youtube]').is(':checked')

      if (upload_to_youtube) {
        $.ajax({
          type: "GET",
          dataType: "json",
          url: "/auth/has_google_auth"
        }).success(function(data) {
          if(data.has_google_auth) {
            performClaim()
          } else {
            var error_ul = $('<ul class="error-text upload_to_youtube"><li>You must sign in to YouTube</li></ul>')
            $('#recording-finished-dialog form [purpose=upload_to_youtube]').addClass('error').append(error_ul)      
          }
        }).always(function () {
          registerClaimRecordingHandlers(true);
        })        
      } else {
        performClaim()
      } 

      return false;
    }

    function performClaim() {
      var name = $('#recording-finished-dialog form input[name=name]').val();
      var description = $('#recording-finished-dialog form textarea[name=description]').val();
      var genre = $('#recording-finished-dialog form select[name=genre]').val();
      var is_public = $('#recording-finished-dialog form input[name=is_public]').is(':checked')
      var save_video = $('#recording-finished-dialog form input[name=save_video]').is(':checked')
      var upload_to_youtube = $('#recording-finished-dialog form input[name=upload_to_youtube]').is(':checked')

      rest.claimRecording({
        id: recording.id,
        name: name,
        description: description,
        genre: genre,
        is_public: is_public,
        save_video: save_video,
        upload_to_youtube: upload_to_youtube
      })
      .done(function () {
        $dialog.data('result', {keep:true});
        app.layout.closeDialog('recordingFinished');
        context.JK.GA.trackMakeRecording();
      })
      .fail(function (jqXHR) {
        if (jqXHR.status == 422) {
          var errors = JSON.parse(jqXHR.responseText);

          var $name_errors = context.JK.format_errors('name', errors);
          if ($name_errors) $('#recording-finished-dialog form input[name=name]').closest('div.field').addClass('error').end().after($name_errors);

          var $description_errors = context.JK.format_errors('description', errors);
          if ($description_errors) $('#recording-finished-dialog form input[name=description]').closest('div.field').addClass('error').end().after($description_errors);

          var $genre_errors = context.JK.format_errors('genre', errors);
          if ($genre_errors) $('#recording-finished-dialog form select[name=genre]').closest('div.field').addClass('error').end().after($genre_errors);

          var $is_public_errors = context.JK.format_errors('is_public', errors);
          if ($is_public_errors) $('#recording-finished-dialog form input[name=is_public]').closest('div.field').addClass('error').end().after($is_public_errors);

          var $save_video_errors = context.JK.format_errors('save_video', errors);
          if ($save_video_errors) $('#recording-finished-dialog form input[name=save_video]').closest('div.field').addClass('error').end().after($save_video_errors);
          
          var recording_error = context.JK.get_first_error('recording_id', errors);

          if (recording_error) context.JK.showErrorDialog(app, "Unable to claim recording.", recording_error);
        }
        else {
          logger.error("unable to claim recording %o", arguments);

          context.JK.showErrorDialog(app, "Unable to claim recording.", jqXHR.responseText);
        }
      })
      .always(function () {
        registerClaimRecordingHandlers(true);
      });
    }

    function registerClaimRecordingHandlers(onOff) {
      $('#keep-session-recording').off('click', claimRecording)
      $('#recording-finished-dialog form').off('submit', claimRecording);
      
      if (onOff) {
        $('#keep-session-recording').on('click', claimRecording);
        $('#recording-finished-dialog form').on('submit', claimRecording);
      }
    }

    function registerDiscardRecordingHandlers(onOff) {
      if (onOff) {
        $('#discard-session-recording').on('click', discardRecording);
      }
      else {
        $('#discard-session-recording').off('click', discardRecording);
      }
    }

    function onPause() {
      logger.debug("calling jamClient.SessionPausePlay");
      context.jamClient.SessionPausePlay();
    }

    function onStop() {
      logger.debug("calling jamClient.SessionStopPlay");
      context.jamClient.SessionStopPlay();
    }

    function onPlay(e, data) {
      logger.debug("calling jamClient.SessionStartPlay");
      context.jamClient.SessionStartPlay(data.playbackMode);
    }

    function onChangePlayPosition(e, data) {
      logger.debug("calling jamClient.SessionTrackSeekMs(" + data.positionMs + ")");
      context.jamClient.SessionTrackSeekMs(data.positionMs);
    }

    function registerStaticEvents() {
      registerClaimRecordingHandlers(true);
      registerDiscardRecordingHandlers(true);
      $(playbackControls)
        .on('stop', onStop)
        .on('pause', onPause)
        .on('play', onPlay)
        .on('change-position', onChangePlayPosition);
      $dialog.find(".google_login_button").on('click', startGoogleLogin);

      // Check for google authorization using AJAX and show/hide the
      // google login button / "signed in" label as appropriate:
      $(window).on('focus', function() {        
        setGoogleAuthState();        
      });      
    }

    function setGoogleAuthState() {
      $.ajax({
        type: "GET",
        dataType: "json",
        url: "/auth/has_google_auth"
      }).success(function(data) {
        if(data.has_google_auth) {
          $("input.google_login_button").addClass("hidden")
          $("span.signed_in_to_google").removeClass("hidden")     
          removeGoogleLoginErrors()   
        } else {
          $("span.signed_in_to_google").addClass("hidden")
          $("input.google_login_button").removeClass("hidden")                      
        }
      })
    }

    function removeGoogleLoginErrors() {
      $("ul.error-text.upload_to_youtube").remove()
      $('#recording-finished-dialog form div[purpose=upload_to_youtube]').removeClass('error')
    }

    function setRecording(recordingData) {
      if (recording != null) {
        //XXX - prevent start/stop recording mashing; protect this dialog
        logger.error("unable to set recording data over existing recording data. this coudld be due to start/stop recording mashing");
        return;
      }
      recording = recordingData;
    }

    function initializeButtons() {
      var isPublic = $('#recording-finished-dialog input[name="is_public"]');
      context.JK.checkbox(isPublic);
      context.JK.checkbox($('#recording-finished-dialog input[name="save_video"]'));
      context.JK.checkbox($('#recording-finished-dialog input[name="upload_to_youtube"]'));
    }

    function initialize() {
      var dialogBindings = {
        'beforeShow': beforeShow,
        'afterHide': afterHide,
        'onCancel': onCancel
      };

      app.bindDialog('recordingFinished', dialogBindings);

      $dialog = $('#recording-finished-dialog')
      playbackControls = new context.JK.PlaybackControls($('#recording-finished-dialog .recording-controls'));

      registerStaticEvents();
      initializeButtons();
    };


    this.initialize = initialize;
    this.setRecording = setRecording;
  }

  return this;
})(window, jQuery);