/*jshint browser:true */
/*global _:false */
//
// Twitch stats interface
// Depends on twitch.core.js
//
// Use this to display stats to users!
// Requires use of a jquery.statchart
// Usage: Twitch.stats
//   Twitch.stats.setup(chart, url)
//
//   chart is the statchart object that will be displaying the stats
//   url is the url called to get available stat types
//
// Examples: see app/views/dashboards/stats.haml
//
// Required DOM elements to use this
//
// id: grouping_selector, class: input, this will display the grouping available for selected stat
// id: stat_selector, class: input, this will display the available stats
// id: resolution_selector, class: input, this will display the available resolutions
// id: date_selector, class: div, will select the month, needs 3 subelements:
//       id: prev, class: a, clicking this will change the month selection to the previous month
//       id: next, class: a, clicking this will change the month selection to the next month
//       id: month, class: select, this is the selector for the month
//
// All of these dom elements and a chart are included in app/views/shared/stats

(function (Twitch, $) {

  var stats = {};

  stats.setup = function (chart, url) {

    var getStatTypes = function (callback) {
      $.loggedInAjax({
        url:url,
        success: function (data, textStatus, jqXHR) {
          // store two representations of stat -> label mapping
          // to work around "limitations" in autocomplete
          var stats = {};
          data.forEach(function (stat) {
            stats[stat.label] = {
              identifier: stat.identifier,
              groupings: stat.groupings,
              resolutions: stat.resolutions
            };
          });
          var statArray = $.makeArray($(data).map(function (i, stat) {return stat.label;})).sort();

          callback(null, stats, statArray);
        }
      });
    };

    var Groups = (function () {
      var groupings = [
        {identifier: "none", label: i18n("None")},
        {identifier: "url", label: i18n("URL")},
        {identifier: "player", label: i18n("Player Type")},
        {identifier: "geo", label: i18n("Geo")},
        {identifier: "live", label: i18n("Live / Archive")},
        {identifier: "host_channel", label: i18n("Host")}
      ];

      var mapping = {};
      groupings.forEach(function (grouping) {
        mapping[grouping.label] = grouping.identifier;
      });

      var groupingArray = $.makeArray($(groupings).map(function (i, grouping) {return grouping.label;}));

      var that = {
        getIdentifier: function (label) {
          return mapping[label];
        },
        createArray: function (identifiers) {
          // Array of available groupings for the stat to feed into
          // autoselect (none is always a valid grouping)
          var available = groupingArray.filter(function (grouping) {
            if (mapping[grouping] === "none") {
              return true;
            }
            return $.inArray(mapping[grouping], identifiers) !== -1;
          });
          return available;
        }
      };
      return that;
    })();

    var Resolutions = (function () {
      var resolutions = [
        {identifier: "hour", label: i18n("Hourly Resolution")},
        {identifier: "day", label: i18n("Daily Resolution")}
      ];

      var mapping = {};
      resolutions.forEach(function (resolutions) {
        mapping[resolutions.label] = resolutions.identifier;
      });

      var resolutionsArray = $.makeArray($(resolutions)
                                         .map(function (i, resolutions) {return resolutions.label;}));

      var that = {
        getIdentifier: function (label) {
          return mapping[label];
        },
        resolutionsArray: resolutionsArray,
        defaultResolution: _.find(resolutions, function (res) { return res.identifier === "hour" ; }).label
      };
      return that;
    })();

    if (typeof Array.prototype.forEach !== "function" ||
        typeof Array.prototype.filter !== "function") {
      $("#chart_container").text(i18n("Sorry, your browser is incompatible with Twitch stats. Please use a recent version of Google Chrome or Mozilla Firefox"));
      return;
    }

    // month selector widget to work around mixpanel's inadequacies
    $('#date_selector #prev').addClass('disabled');
    $('#date_selector > select#month').change(function (e) {
      var selected = $('#date_selector > select#month option:selected');
      var prev = $('#date_selector #prev');
      var next = $('#date_selector #next');
      if (!selected.next().length) {
        prev.removeClass('disabled');
        next.addClass('disabled');
      } else if (!selected.prev().length) {
        prev.addClass('disabled');
        next.removeClass('disabled');
      } else {
        prev.removeClass('disabled');
        next.removeClass('disabled');
      }

      chart.month($(this).find(':selected').val());
      chart.reload();
    });
    $('#date_selector #prev, #next').click(function (e) {
      var newSelect = $('#date_selector > select#month option:selected');
      if (this.id === 'prev') {
        newSelect = newSelect.prev();
      } else {
        newSelect = newSelect.next();
      }
      if (newSelect.length) {
        $('#date_selector > select#month').val(newSelect.val()).change();
      }
    });

    getStatTypes(function (err, statObj, statArray) {
      var $statSelector = $('#stat_selector').autocomplete({
        source: statArray,
        delay: 0,
        minLength: 0
      });

      var $groupingSelector = $('#grouping_selector').autocomplete({
        delay: 0,
        minLength: 0
      });

      var $resolutionSelector = $("#resolution_selector").autocomplete({
        delay: 0,
        minLength: 0,
        source: Resolutions.resolutionsArray
      });

      $resolutionSelector.val(Resolutions.defaultResolution);

      var changeStat = function (label) {
        var availableGroupings = Groups.createArray(statObj[label].groupings);
        $groupingSelector.autocomplete('option', 'source', availableGroupings);

        if ($.inArray(chart.grouping(), availableGroupings) === -1) {
          chart.grouping('none');
          $groupingSelector.val('');
        }
        if (availableGroupings.length === 1) {
          // no groupings besides 'none'
          $groupingSelector.attr("disabled", true);
        } else {
          $groupingSelector.removeAttr("disabled");
        }

        chart.load(statObj[label].identifier);
      };

      [$statSelector, $groupingSelector, $resolutionSelector].forEach(function ($selector) {
        $selector.bind('focus', function (e) {
          // force suggestions box open on focus
          $(this).autocomplete('search', '');
        });
      });

      $statSelector.bind('autocompleteselect', function (event, ui) {
        changeStat(ui.item.value);
        $(this).blur();
      });

      $resolutionSelector.bind('autocompleteselect', function (event, ui) {
        var identifier = Resolutions.getIdentifier(ui.item.value);
        chart.resolution(identifier).reload();
        $(this).blur();
      });

      $groupingSelector.bind('autocompleteselect', function (event, ui) {
        var identifier = Groups.getIdentifier(ui.item.value);
        if (identifier === "none") {
          $(this).val('');
          event.preventDefault();
        }

        chart.grouping(identifier).reload();

        $(this).blur();
      });

      var defaultStat = i18n('Video Plays');
      $statSelector.val(defaultStat);
      changeStat(defaultStat);
    });
  };

  Twitch.mixin({
    stats: stats
  });

})(Twitch, jQuery);
