(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;
    var $saveVideoCheckbox = null
    var $uploadToYoutube = null
    var timeout = null
    var CLIENT_ROLE = context.JK.CLIENT_ROLE

    function resetForm() {
      // remove all display errors
      $('#recording-finished-dialog form .error-text').remove()
      $('#recording-finished-dialog form .error').removeClass("error")
      if(recording.video) {
        if(recording.owner.id == context.JK.currentUserId) {
          // only the owner of the video gets to see video options
          $dialog.find('.save-video').show()
          $dialog.find('.upload-to-youtube').show()
        }
        else {
          $dialog.find('.save-video').hide()
          $dialog.find('.upload-to-youtube').hide()
        }

      }
      else {
        $dialog.find('.save-video').hide()
        $dialog.find('.upload-to-youtube').hide()
      }
      removeGoogleLoginErrors()
    }

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

      resetForm();

      if(context.jamClient.getClientParentChildRole() == CLIENT_ROLE.CHILD) {

        logger.debug("child client; launching preview after xfer");
        $('#recording-finished-dialog span.nowait').addClass('hidden')
        $('#recording-finished-dialog span.pleasewait').removeClass('hidden')
        $('#recording-finished-dialog .preview-area').css('visibility', 'hidden')
        $('#recording-finished-dialog form').css('visibility', 'hidden')
        waitForMixTransfer()
      }
      else {
        console.log("normal client; launching preview immediately")
        $('#recording-finished-dialog span.pleasewait').addClass('hidden')
        $('#recording-finished-dialog span.nowait').removeClass('hidden')
        $('#recording-finished-dialog .preview-area').css('visibility', 'visible')
        $('#recording-finished-dialog form').css('visibility', 'visible')
        launchPreview();
      }

    }


    function waitForMixTransfer() {
      timeout = setTimeout(function() {
        console.log("checking for file transfer", window.RecordingStore.mixTransferred)

        if(window.RecordingStore.mixTransferred) {
          $('#recording-finished-dialog span.pleasewait').addClass('hidden')
          $('#recording-finished-dialog span.nowait').removeClass('hidden')
          $('#recording-finished-dialog .preview-area').css('visibility', 'visible')
          $('#recording-finished-dialog form').css('visibility', 'visible')
          timeout = null
          launchPreview()
        }
        else {
          waitForMixTransfer();
        }

      }, 1000)
    }

    function launchPreview() {
      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", recording, 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() {
      if(timeout) {
        clearTimeout(timeout)
        timeout = null
      }
      if(recording && recording.video) {
        var name = $('#recording-finished-dialog form input[name=name]').val();
        name = name.replace(/[^A-Za-z0-9\-\ ]/g, '');


        var saveToDisk = $('#recording-finished-dialog form input[name=save_video]').is(':checked')
        var keepResult = $dialog.data('result');
        keepResult = keepResult && keepResult.keep

        logger.debug("VideoDecision rid:" + recording.id + ", name=" + name + ", keepResult=" + keepResult + ", saveToDisk=" + saveToDisk);

        context.jamClient.VideoDecision(recording.id, name, keepResult && saveToDisk)
      }

      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()
        logger.debug("closing window")
        setGoogleAuthState()
      }
      return false;
    }

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

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

      upload_to_youtube = false // don't prevent user from getting through dialog because popup now handles auth

      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')

      var recording_id = recording.id
      var recording_video = recording.video

      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();
          if(recording_video && save_video && upload_to_youtube) {
            // you have to have elected to save video to have upload to youtube have
            context.VideoUploaderActions.showUploader(recording_id);
          }

      })
      .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() {
      $saveVideoCheckbox = $('#recording-finished-dialog input[name="save_video"]')
      $uploadToYoutube = $('#recording-finished-dialog input[name="upload_to_youtube"]')
      var isPublic = $('#recording-finished-dialog input[name="is_public"]');
      context.JK.checkbox(isPublic);
      context.JK.checkbox($saveVideoCheckbox);
      context.JK.checkbox($uploadToYoutube);

      $saveVideoCheckbox.on('ifChanged', function() {
        var saveVideoToDisk = $saveVideoCheckbox.is(':checked')

        if(saveVideoToDisk) {
          $uploadToYoutube.iCheck('enable')
        }
        else {
          $uploadToYoutube.iCheck('disable')
        }

      })
    }

    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);