angular.module('cesium.graph.docstats.controllers', ['chart.js', 'cesium.graph.services', 'cesium.graph.common.controllers'])

  .config(function($stateProvider, PluginServiceProvider, csConfig) {
    'ngInject';

    $stateProvider
      .state('app.doc_stats_lg', {
        url: "/data/stats?stepUnit&t&hide&scale",
        views: {
          'menuContent': {
            templateUrl: "plugins/graph/templates/docstats/view_stats.html",
            controller: 'GpDocStatsCtrl'
          }
        }
      });

    var enable = csConfig.plugins && csConfig.plugins.es;
    if (enable) {
      // TODO: add buttons to link with doc stats
    }
  })


  .controller('GpDocStatsCtrl', GpDocStatsController)
;

function GpDocStatsController($scope, $state, $controller, $q, $translate, gpColor, gpData, $filter) {
  'ngInject';

  // Initialize the super class and extend it.
  angular.extend(this, $controller('GpCurrencyAbstractCtrl', {$scope: $scope}));

  $scope.displayRightAxis = true;
  $scope.hiddenDatasets = [];

  $scope.chartIdPrefix = 'docstats-chart-';
  $scope.charts = [

    // User count
    {
      id: 'user',
      title: 'GRAPH.DOC_STATS.USER.TITLE',
      series: [
        {
          key: 'user_profile',
          label: 'GRAPH.DOC_STATS.USER.USER_PROFILE',
          color: gpColor.rgba.royal(0.7),
          pointHoverBackgroundColor: gpColor.rgba.royal(),
          clickState: {
            name: 'app.document_search',
            params: {index:'user', type: 'profile'}
          }
        },
        {
          key: 'user_settings',
          label: 'GRAPH.DOC_STATS.USER.USER_SETTINGS',
          color: gpColor.rgba.gray(0.5),
          pointHoverBackgroundColor: gpColor.rgba.gray(),
          clickState: {
            name: 'app.document_search',
            params: {index:'user', type: 'settings'}
          }
        }
      ]
    },

    // User delta
    {
      id: 'user_delta',
      title: 'GRAPH.DOC_STATS.USER_DELTA.TITLE',
      series: [
        {
          key: 'user_profile_delta',
          label: 'GRAPH.DOC_STATS.USER_DELTA.USER_PROFILE',
          type: 'line',
          yAxisID: 'y-axis-delta',
          color: gpColor.rgba.royal(),
          pointHoverBackgroundColor: gpColor.rgba.royal()
        },
        {
          key: 'user_settings_delta',
          label: 'GRAPH.DOC_STATS.USER_DELTA.USER_SETTINGS',
          type: 'line',
          yAxisID: 'y-axis-delta',
          color: gpColor.rgba.gray(0.5),
          pointHoverBackgroundColor: gpColor.rgba.gray()
        }
      ]
    },

    // Message & Co.
    {
      id: 'message',
      title: 'GRAPH.DOC_STATS.MESSAGE.TITLE',
      series: [
        {
          key: 'message_inbox',
          label: 'GRAPH.DOC_STATS.MESSAGE.MESSAGE_INBOX',
          color: gpColor.rgba.royal(),
          pointHoverBackgroundColor: gpColor.rgba.royal(),
          clickState: {
            name: 'app.document_search',
            params: {index:'message', type: 'inbox'}
          }
        },
        {
          key: 'message_outbox',
          label: 'GRAPH.DOC_STATS.MESSAGE.MESSAGE_OUTBOX',
          color: gpColor.rgba.calm(),
          pointHoverBackgroundColor: gpColor.rgba.calm(),
          clickState: {
            name: 'app.document_search',
            params: {index:'message', type: 'outbox'}
          }
        },
        {
          key: 'invitation_certification',
          label: 'GRAPH.DOC_STATS.MESSAGE.INVITATION_CERTIFICATION',
          color: gpColor.rgba.gray(0.5),
          pointHoverBackgroundColor: gpColor.rgba.gray(),
          clickState: {
            name: 'app.document_search',
            params: {index:'invitation', type: 'certification'}
          }
        }
      ]
    },

    // Social Page & group
    {
      id: 'social',
      title: 'GRAPH.DOC_STATS.SOCIAL.TITLE',
      series: [
        {
          key: 'page_record',
          label: 'GRAPH.DOC_STATS.SOCIAL.PAGE_RECORD',
          color: gpColor.rgba.royal(),
          pointHoverBackgroundColor: gpColor.rgba.royal(),
          clickState: {
            name: 'app.document_search',
            params: {index:'page', type: 'record'}
          }
        },
        {
          key: 'group_record',
          label: 'GRAPH.DOC_STATS.SOCIAL.GROUP_RECORD',
          color: gpColor.rgba.calm(),
          pointHoverBackgroundColor: gpColor.rgba.calm(),
          clickState: {
            name: 'app.document_search',
            params: {index:'group', type: 'record'}
          }
        },
        {
          key: 'page_comment',
          label: 'GRAPH.DOC_STATS.SOCIAL.PAGE_COMMENT',
          color: gpColor.rgba.gray(0.5),
          pointHoverBackgroundColor: gpColor.rgba.gray(),
          clickState: {
            name: 'app.document_search',
            params: {index:'page', type: 'comment'}
          }
        }
      ]
    },

    // Other: deletion, doc, etc.
    {
      id: 'other',
      title: 'GRAPH.DOC_STATS.OTHER.TITLE',
      series: [
        {
          key: 'history_delete',
          label: 'GRAPH.DOC_STATS.OTHER.HISTORY_DELETE',
          color: gpColor.rgba.gray(0.5),
          pointHoverBackgroundColor: gpColor.rgba.gray(),
          clickState: {
            name: 'app.document_search',
            params: {index:'history', type: 'delete'}
          }
        }
      ]
    }
  ];

  var formatInteger = $filter('formatInteger');

  $scope.defaultChartOptions = {
    responsive: true,
    maintainAspectRatio: $scope.maintainAspectRatio,
    title: {
      display: true
    },
    legend: {
      display: true,
      onClick: $scope.onLegendClick
    },
    scales: {
      xAxes: [{
        stacked: true
      }],
      yAxes: [
        {
          id: 'y-axis',
          stacked: true
        },
        {
          id: 'y-axis-delta',
          stacked: false
        },
        {
          id: 'y-axis-delta-right',
          stacked: false,
          display: $scope.displayRightAxis,
          position: 'right',
          gridLines: {
            drawOnChartArea: false
          }
        }
      ]
    },
    tooltips: {
      enabled: true,
      intersect: false,
      mode: 'index',
      callbacks: {
        label: function(tooltipItems, data) {
          return data.datasets[tooltipItems.datasetIndex].label +
            ': ' + formatInteger(tooltipItems.yLabel);
        }
      }
    }
  };

  $scope.init = function(e, state) {
    if (state && state.stateParams) {
      // Manage URL parameters
    }
  };

  $scope.load = function(updateTimePct) {

    return $q.all([
      // Get i18n keys (chart title, series labels, date patterns)
      $translate($scope.charts.reduce(function(res, chart) {
        return res.concat(chart.series.reduce(function(res, serie) {
          return res.concat(serie.label);
        }, [chart.title]));
      }, [
        'COMMON.DATE_PATTERN',
        'COMMON.DATE_SHORT_PATTERN',
        'COMMON.DATE_MONTH_YEAR_PATTERN'
      ])),

      // get Data
      gpData.docstat.get($scope.formData)
    ])
    .then(function(result) {
      var translations = result[0];
      var datePatterns = {
        hour: translations['COMMON.DATE_PATTERN'],
        day: translations['COMMON.DATE_SHORT_PATTERN'],
        month: translations['COMMON.DATE_MONTH_YEAR_PATTERN']
      };

      result = result[1];
      if (!result || !result.times) return; // no data
      $scope.times = result.times;

      // Labels
      var labelPattern = datePatterns[$scope.formData.rangeDuration];
      $scope.labels = _.map(result.times, function(time) {
        return moment.unix(time).local().format(labelPattern);
      });

      // Update range options with received values
      $scope.updateRange(result.times[0], result.times[result.times.length-1], updateTimePct);

      $scope.setScale($scope.scale);

      // For each chart
      _.forEach($scope.charts, function(chart){

        // Prepare chart data
        var usedYAxisIDs = {};
        chart.data = _.map(chart.series, function(serie) {
          usedYAxisIDs[serie.yAxisID||'y-axis'] = true;
          // If 'delta' serie, then compute delta from the source serie
          if (serie.key.endsWith('_delta')) {
            var key = serie.key.substring(0, serie.key.length - '_delta'.length);
            return getDeltaFromValueArray(result[key]) || [];
          }
          return result[serie.key]||[];
        });

        // Options (with title)
        chart.options = angular.copy($scope.defaultChartOptions);
        chart.options.title.text = translations[chart.title];

        // Remove unused yAxis
        chart.options.scales.yAxes = chart.options.scales.yAxes.reduce(function(res, yAxe){
          return usedYAxisIDs[yAxe.id] ? res.concat(yAxe) : res;
        }, []);

        // Series datasets
        chart.datasetOverride = _.map(chart.series, function(serie) {
          return {
            yAxisID: serie.yAxisID || 'y-axis',
            type: serie.type || 'line',
            label: translations[serie.label],
            fill: serie.type !== 'line',
            borderWidth: 2,
            pointRadius: serie.type !== 'line' ? 0 : 2,
            pointHitRadius: 4,
            pointHoverRadius: 3,
            borderColor: serie.color,
            backgroundColor: serie.color,
            pointBackgroundColor: serie.color,
            pointBorderColor: serie.color,
            pointHoverBackgroundColor: serie.pointHoverBackgroundColor||serie.color,
            pointHoverBorderColor: serie.pointHoverBorderColor||gpColor.rgba.white()
          };
        });
      });
    });

  };

  $scope.onChartClick = function(data, e, item) {
    if (!item) return;
    var chart = _.find($scope.charts , function(chart) {
      return ($scope.chartIdPrefix  + chart.id) == item._chart.canvas.id;
    });

    var serie = chart.series[item._datasetIndex];

    if (serie && serie.clickState && serie.clickState.name) {
      var stateParams = serie.clickState.params ? angular.copy(serie.clickState.params) : {};

      // Compute query
      var from = $scope.times[item._index];
      var to = moment.unix(from).utc().add(1, $scope.formData.rangeDuration).unix();
      stateParams.q = 'time:>={0} AND time:<{1}'.format(from, to);

      return $state.go(serie.clickState.name, stateParams);
    }
    else {
      console.debug('Click on item index={0} on range [{1},{2}]'.format(item._index, from, to));
    }
  };

  function getDeltaFromValueArray(values) {
    if (!values) return undefined;
    var previousValue;
    return _.map(values, function(value) {
      var newValue = (value !== undefined) && (value - (previousValue || value)) || undefined;
      previousValue = value;
      return newValue;
    });
  }

}