(function (context, $) {

  "use strict";

  context.JK = context.JK || {};

  context.JK.AccountSessionProperties = function (app) {
    var logger = context.JK.logger;
    var rest = context.JK.Rest();
    var sessionId = null;
    var sessionData = null;
    var $screen = $("#account-session-properties");
    var $inputFiles = $screen.find('#session-select-files');
    var $selectedFilenames = $screen.find('#selected-filenames');
    var $propertiesBody = null;
    var $languageList = null;
    var $recurringModeList = null;
    var $timezoneList = null;
    var $startTimeList = null;
    var $endTimeList = null;
    var $sessionName = null;
    var $sessionDescription = null;
    var $musicianAccess = null;
    var $fansAccess = null;
    var $musicNotations = null;
    var $btnSelectFiles = null;
    var $uploadSpinner = null;
    var $dateTimeTBD = null;
    var $actionBar = null;

    var ONE_HOUR = 3600 * 1000;
    var ONE_MINUTE = 60 * 1000;
    var ONE_DAY = ONE_HOUR * 24;

    var defaultTimeArray = ["12:00 AM", "12:30 AM", "01:00 AM", "01:30 AM", "02:00 AM", "02:30 AM",
      "03:00 AM", "03:30 AM", "04:00 AM", "04:30 AM", "05:00 AM", "05:30 AM", "06:00 AM", "06:30 AM",
      "07:00 AM", "07:30 AM", "08:00 AM", "08:30 AM", "09:00 AM", "09:30 AM", "10:00 AM", "10:30 AM",
      "11:00 AM", "11:30 AM", "12:00 PM", "12:30 PM", "01:00 PM", "01:30 PM", "02:00 PM", "02:30 PM",
      "03:00 PM", "03:30 PM", "04:00 PM", "04:30 PM", "05:00 PM", "05:30 PM", "06:00 PM", "06:30 PM",
      "07:00 PM", "07:30 PM", "08:00 PM", "08:30 PM", "09:00 PM", "09:30 PM", "10:00 PM", "10:30 PM",
      "11:00 PM", "11:30 PM"];

    function beforeShow(data) {
      sessionId = data.id;
      loadSessionData();
    }

    function afterShow(data) {
    }

    function toggleDateTBD(e) {
      var status = $(e.target)[0].checked;
      var $dateField = $screen.find('#session-prop-start-date');
      if (status) {
        $dateField.datepicker("disable");
      }
      else {
        $dateField.datepicker("enable");
        if ($dateField.val() == "") {
          $dateField.val(new Date().toDateString());
        }
        toggleDate();
      }
    }

    function events() {
      $startTimeList.on('change', toggleStartTime);
      $dateTimeTBD.on('ifChanged', toggleDateTBD);
      $screen.find("#session-update").on('click', updateSessionProperties);

      $inputFiles.on('change', changeSelectedFiles);
      $btnSelectFiles.on('click', toggleSelectFiles);
    }

    function toggleStartTime() {
      var valueSelected = $startTimeList.find('option:selected').val();
      var startIndex = defaultTimeArray.indexOf(valueSelected) + 1;

      $endTimeList.empty();
//      if (startIndex == defaultTimeArray.length ) {
//        var strTime = defaultTimeArray[0];
//        $endTimeList.append($('<option value="' + strTime + '" class="label">' + strTime +'</option>'));
//      }

      var endIndex = startIndex + 6;
      var endTimeIndices = [];
      for (var i = startIndex; i < endIndex; i++) {
        if (i < defaultTimeArray.length) {
          endTimeIndices.push(i);
        }
        else {
          endTimeIndices.push(i - defaultTimeArray.length);
        }
      }

      $.each(endTimeIndices, function(index, value) {
        var strTime = defaultTimeArray[value];
        $endTimeList.append($('<option value="' + strTime + '" class="label">' + strTime +'</option>'));
      });

      $endTimeList.val(defaultTimeArray[(startIndex + 1) % defaultTimeArray.length]);

      context.JK.dropdown($endTimeList);
    }

    function getFormattedTime(date, change) {
      if (change) {
        date.setMinutes(Math.ceil(date.getMinutes() / 30) * 30);
      }
      var h12h = date.getHours();
      var m12h = date.getMinutes();
      var ampm;
      if (h12h >= 0 && h12h < 12) {
        if (h12h === 0) {
          h12h = 12; // 0 becomes 12
        }
        ampm = "AM";
      }
      else {
        if (h12h > 12) {
          h12h -= 12; // 13-23 becomes 1-11
        }
        ampm = "PM";
      }
      var timeString = ("00" + h12h).slice(-2) + ":" + ("00" + m12h).slice(-2) + " " + ampm;

      return timeString;
    }

    function toggleDate(startTime) {
      var selectedDate = null;
      if ($screen.find("#session-prop-start-date").val() == "") {
        selectedDate = new Date();
      }
      else {
        selectedDate = new Date($screen.find('#session-prop-start-date').val());
      }
      var currentDate = new Date();
      var startIndex = 0;

      if (currentDate.getYear() == selectedDate.getYear() &&
        currentDate.getMonth() == selectedDate.getMonth() &&
        currentDate.getDate() == selectedDate.getDate()) {

        var timeString = getFormattedTime(currentDate, true);
        startIndex = defaultTimeArray.indexOf(timeString);
        if (startTime != null) {
          var curStartIndex = defaultTimeArray.indexOf(startTime);
          if (curStartIndex < startIndex) {
            startIndex = curStartIndex;
          }
        }
      }
      $startTimeList.empty();
      for (var i = startIndex; i < defaultTimeArray.length; i++) {
        var strTime = defaultTimeArray[i];
        $startTimeList.append($('<option value="' + strTime + '" class="label">' + strTime +'</option>'));
      }

      toggleStartTime();

      context.JK.dropdown($startTimeList);
      context.JK.dropdown($endTimeList);
    }

    function validateForm() {
      var isValid = true;
      var name = $sessionName.val();
      if (!name) {
        $screen.find('#divSessionName .error-text').remove();
        $screen.find('#divSessionName').addClass("error");
        $sessionName.after("<ul class='error-text'><li>Name is required</li></ul>");
        isValid = false;
      }
      else {
        $screen.find('#divSessionName').removeClass("error");
      }

      var description = $sessionDescription.val();
      if (!description) {
        $screen.find('#divSessionDescription .error-text').remove();
        $screen.find('#divSessionDescription').addClass("error");
        $sessionDescription.after("<ul class='error-text'><li>Description is required</li></ul>");
        isValid = false;
      }
      else {
        $screen.find('#divSessionDescription').removeClass("error");
      }

      var genres = context.JK.GenreSelectorHelper.getSelectedGenres('#session-prop-genre');

      if (genres.length === 0) {
        $screen.find('#divSessionGenre .error-text').remove();
        $screen.find('#divSessionGenre').addClass("error");
        $screen.find('#session-prop-genre').after("<ul class='error-text'><li>You must select a genre.</li></ul>");
        isValid = false;
      }
      else {
        $screen.find('#divSessionGenre').removeClass("error");
      }

      return isValid;
    }

    function updateSessionProperties(e) {
      e.preventDefault();

      if (validateForm() == false)
        return;

      var data = {};
      data.name = $sessionName.val();
      data.description = $sessionDescription.val();
      data.genres = context.JK.GenreSelectorHelper.getSelectedGenres("#session-prop-genre");
      if ($musicianAccess.val() == 'only-rsvp') {
        data.musician_access = false;
        data.approval_required = false;
      }
      else if ($musicianAccess.val() == 'musicians-approval') {
        data.musician_access = true;
        data.approval_required = true;
      }
      else if ($musicianAccess.val() == 'musicians') {
        data.musician_access = true;
        data.approval_required = false;
      }

      if ($fansAccess.val() == 'no-listen-chat') {
        data.fan_access = false; data.fan_chat = false;
      }
      else if ($fansAccess.val() == 'listen-chat-each') {
        data.fan_access = true; data.fan_chat = false;
      }
      else if ($fansAccess.val() == 'listen-chat-band') {
        data.fan_access = true; data.fan_chat = true;
      }
      data.legal_policy = $screen.find('#session-policy').val();
      data.language = $languageList.val();
      if ($dateTimeTBD[0].checked) {
        data.start = null;
      }
      else {
        data.start = $screen.find('#session-prop-start-date').val() + ' ' + $startTimeList.val();
        var startIndex = defaultTimeArray.indexOf($startTimeList.val());
        var endIndex = defaultTimeArray.indexOf($endTimeList.val());
        if (endIndex > startIndex) {
          data.duration = (endIndex - startIndex) * 30;
        }
        else {
          data.duration = (endIndex + defaultTimeArray.length - startIndex + 1) * 30;
        }
//        var endDate = new Date($screen.find('#session-prop-start-date').val() + ' ' + $endTimeList.val());
//        data.duration = (endDate - new Date(data.start)) / ONE_MINUTE;
//        if ($endTimeList.val() == defaultTimeArray[0]) {
//          data.duration += ONE_DAY / ONE_MINUTE;
//        }
      }
      data.recurring_mode = $recurringModeList.val();
      data.music_notations = JSON.stringify(sessionData.music_notations);
      console.log("data.music_notations=%o", data.music_notations);
      data.timezone = $timezoneList.val();
      data.open_rsvps = $screen.find("#open-rsvp")[0].checked;

      rest.updateScheduledSession(sessionData.id, data)
        .done(function(response) {
          loadSessionData();
          app.notifyAlert("Session is successfully updated.");
        })
        .fail(app.ajaxError);
    }

    function initializeControls() {
      $screen.find("#session-prop-start-date").datepicker({
          dateFormat: "D d MM yy",
          onSelect: toggleDate
        }
      );

      $screen.find(".icheckbuttons input").iCheck({
        checkboxClass: 'icheckbox_minimal',
        radioClass: 'iradio_minimal',
        inheritClass: true
      });

      context.JK.GenreSelectorHelper.render('#session-prop-genre');

      context.JK.dropdown($musicianAccess);
      context.JK.dropdown($fansAccess);
      context.JK.dropdown($screen.find('#session-policy'));
      context.JK.dropdown($timezoneList);
      context.JK.dropdown($recurringModeList);
      context.JK.dropdown($languageList);
    }

    function loadSessionData() {
      rest.getSessionHistory(sessionId)
        .done(renderSession)
        .fail(app.ajaxError);
    }

    function getDiffIndex(duration) {
      if (!duration) {
        return 0;
      }
      else {
        var tokens = duration.split(':');
        return parseInt(tokens[0]) * 2 + parseInt(tokens[1]) / 30;
      }
    }

    function uploadNotations(notations) {
      var formData = new FormData();
      var maxExceeded = false;

      $.each(notations, function(i, file) {
        var max =  10 * 1024 * 1024;
        if(file.size > max) {
          maxExceeded = true;
          return false;
        }
        formData.append('files[]', file);
      });

      if(maxExceeded) {
        app.notify(
          { title: "Maximum Music Notation Size Exceeded",
            text: "You can only upload files up to 10 megabytes in size."
          });
        var deferred = new $.Deferred();
        deferred.reject();
        return deferred;
      }

      formData.append('client_id', app.clientId);
      //formData.append('session_id', sessionId);
      $btnSelectFiles.text('UPLOADING...').data('uploading', true)
      $uploadSpinner.show();
      return rest.uploadMusicNotations(formData)
        .done(function(response) {
          var error_files = [];
          $.each(response, function(i, music_notation) {
            $actionBar.css("margin-top", parseInt($actionBar.css("margin-top")) + 20);
            if (music_notation.errors) {
              error_files.push(sessionData.music_notations[i].name);
            }
          });
          if (error_files.length > 0) {
            app.notifyAlert("Failed to upload notations.", error_files.join(', '));
          }

          sessionData.music_notations = $.merge(sessionData.music_notations, response);
        })
        .fail(function(jqXHR) {
          if(jqXHR.status == 413) {
            // the file is too big.   Let the user know.
            // This should happen when they select the file, but a misconfiguration on the server could cause this.
            app.notify(
              { title: "Maximum Music Notation Size Exceeded",
                text: "You can only upload files up to 10 megabytes in size."
              })
          }
          else {
            app.notifyServerError(jqXHR, "Unable to upload music notations");
          }
        })
        .always(function() {
          $btnSelectFiles.text('SELECT FILES...').data('uploading', null)
          $uploadSpinner.hide();
        })
    }

    function changeSelectedFiles() {
      var fileNames = [];
      var files = $inputFiles.get(0).files;
      var error = false;
      for (var i = 0; i < files.length; ++i) {
        var name = files.item(i).name;
        var ext = name.split('.').pop().toLowerCase();
        if ($.inArray(ext, ["pdf", "png", "jpg", "jpeg", "gif", "xml", "mxl", "txt"]) == -1) {
          error = true;
          break;
        }
        fileNames.push(name);
      }

      if (error) {
        app.notifyAlert("Error", "We're sorry, but you can only upload images (.png .jpg .jpeg .gif), text (.txt), PDFs (.pdf), and XML files (.xml .mxl).");
        $inputFiles.replaceWith($inputFiles.clone(true));
      }
      else {
        // upload as soon as user picks their files.
        uploadNotations($inputFiles.get(0).files)
          .done(function() {
            context._.each(fileNames, function(fileName) {
              var $text = $('<span>').text(fileName);
              var $file = $('<li>').append($text);
              $selectedFilenames.append($file);
            })
          })
      }
    }

    function toggleSelectFiles(event) {
      if($btnSelectFiles.data('uploading')) {
        logger.debug("ignoring click of SELECT FILES... while uploading");
        return false;
      }

      event.preventDefault();
      $inputFiles.trigger('click');
      return false;
    }

    function renderSession(data) {
      sessionData = data;

      if (sessionData.scheduled_start == null) {
        $screen.find("#session-prop-start-date").datepicker("disable");
        $dateTimeTBD.iCheck('check').attr('checked', true);
      }
      else {
        $screen.find('#session-prop-start-date').val(sessionData.scheduled_start_date);
        $dateTimeTBD.iCheck('uncheck').attr('checked', false);
      }

      var startTime = getFormattedTime(new Date(sessionData.scheduled_start), false);
      toggleDate(startTime);
      var diffIndex = getDiffIndex(sessionData.scheduled_duration);
      var endTime = defaultTimeArray[defaultTimeArray.indexOf(startTime) + diffIndex];
      $startTimeList.val(startTime);
      toggleStartTime();
      $endTimeList.val(endTime);
      if (sessionData.timezone == null) {
        context.JK.SessionUtils.defaultTimezone($timezoneList);
      }
      else {
        $timezoneList.val(sessionData.timezone);
      }
      $recurringModeList.val(sessionData.recurring_mode);
      context.JK.GenreSelectorHelper.setSelectedGenres('#session-prop-genre', sessionData.genres);
      $sessionName.val(sessionData.name);
      $sessionDescription.val(sessionData.description);
      $languageList.val(sessionData.language);
      if (sessionData.open_rsvps) {
        $screen.find("#open-rsvp").iCheck("check").attr("checked", true);
      }
      else {
        $screen.find("#open-rsvp").iCheck("uncheck").attr("checked", false);
      }

      sessionData.musician_access_value = 'musicians';
      if (sessionData.musician_access == true && sessionData.approval_required == true)
        sessionData.musician_access_value = 'musicians-approval';
      else if (sessionData.musician_access == false && sessionData.approval_required == false)
        sessionData.musician_access_value = 'only-rsvp';

      sessionData.fans_access_value = 'listen-chat-each';
      if (sessionData.fan_access == true && sessionData.fan_chat == true)
        sessionData.fans_access_value = 'listen-chat-band';
      else if (sessionData.fan_access == false && sessionData.fan_chat == false)
        sessionData.fans_access_value = 'no-listen-chat';

      $musicianAccess.val(sessionData.musician_access_value);
      $fansAccess.val(sessionData.fans_access_value);
      $screen.find('#session-policy').val(sessionData.legal_policy);

      $selectedFilenames.empty();
      context._.each(sessionData.music_notations, function(notation) {
        var $link = notation.viewable ? $('<a href="' + notation.file_url + '" rel="external">').html(notation.file_name) : '#';
        var $text = $('<span>').html($link);
        var $file = $('<li>').append($text);
        $musicNotations.append($file);
      })
    }

    function initialize() {
      var screenBindings = {
        'beforeShow': beforeShow,
        'afterShow': afterShow
      };

      app.bindScreen('account/sessionProperties', screenBindings);

      $propertiesBody = $screen.find("#account-session-properties-div");
      $recurringModeList = $screen.find("#recurring-mode-prop-list");
      $languageList = $screen.find("#session-prop-lang-list");
      $timezoneList = $screen.find("#timezone-prop-list");
      $startTimeList = $screen.find("#start-time-prop-list");
      $endTimeList = $screen.find("#end-time-prop-list");
      $sessionName = $screen.find("#session-prop-name");
      $sessionDescription = $screen.find("#session-prop-desc");
      $musicianAccess = $screen.find("#session-prop-musician-access");
      $fansAccess = $screen.find("#session-prop-fans-access");
      $musicNotations = $screen.find("#selected-filenames");
      $btnSelectFiles = $screen.find(".btn-select-files");
      $uploadSpinner = $screen.find(".upload-spinner");
      $dateTimeTBD = $screen.find("#date_time_tbd");
      $actionBar = $screen.find(".action-bar");

      initializeControls();
      events();
    }

    this.initialize = initialize;
    this.beforeShow = beforeShow;
    this.afterShow = afterShow;

    return this;
  };

})(window, jQuery);