define([
  'lodash'
],
function (_) {
  'use strict';

  return {
    metricAggTypes: [
      {text: "Count",   value: 'count', requiresField: false},
      {text: "Average",  value: 'avg', requiresField: true, supportsInlineScript: true, supportsMissing: true},
      {text: "Sum",  value: 'sum', requiresField: true, supportsInlineScript: true, supportsMissing: true},
      {text: "Max",  value: 'max', requiresField: true, supportsInlineScript: true, supportsMissing: true},
      {text: "Min",  value: 'min', requiresField: true, supportsInlineScript: true, supportsMissing: true},
      {text: "Extended Stats",  value: 'extended_stats', requiresField: true, supportsMissing: true, supportsInlineScript: true},
      {text: "Percentiles",  value: 'percentiles', requiresField: true, supportsMissing: true, supportsInlineScript: true},
      {text: "Unique Count", value: "cardinality", requiresField: true, supportsMissing: true},
      {text: "Moving Average",  value: 'moving_avg', requiresField: false, isPipelineAgg: true, minVersion: 2},
      {text: "Derivative",  value: 'derivative', requiresField: false, isPipelineAgg: true, minVersion: 2 },
      {text: "Raw Document", value: "raw_document", requiresField: false}
    ],

    bucketAggTypes: [
      {text: "Terms",           value: 'terms', requiresField: true},
      {text: "Filters",         value: 'filters' },
      {text: "Geo Hash Grid",   value: 'geohash_grid', requiresField: true},
      {text: "Date Histogram",  value: 'date_histogram', requiresField: true},
    ],

    orderByOptions: [
      {text: "Doc Count",  value: '_count' },
      {text: "Term value", value: '_term' },
    ],

    orderOptions: [
      {text: "Top",     value: 'desc' },
      {text: "Bottom",  value: 'asc' },
    ],

    sizeOptions: [
      {text: "No limit", value: '0' },
      {text: "1", value: '1' },
      {text: "2", value: '2' },
      {text: "3", value: '3' },
      {text: "5", value: '5' },
      {text: "10", value: '10' },
      {text: "15", value: '15' },
      {text: "20", value: '20' },
    ],

    extendedStats: [
      {text: 'Avg', value: 'avg'},
      {text: 'Min', value: 'min'},
      {text: 'Max', value: 'max'},
      {text: 'Sum', value: 'sum'},
      {text: 'Count', value: 'count'},
      {text: 'Std Dev', value: 'std_deviation'},
      {text: 'Std Dev Upper', value: 'std_deviation_bounds_upper'},
      {text: 'Std Dev Lower', value: 'std_deviation_bounds_lower'},
    ],

    intervalOptions: [
      {text: 'auto', value: 'auto'},
      {text: '10s', value: '10s'},
      {text: '1m', value: '1m'},
      {text: '5m', value: '5m'},
      {text: '10m', value: '10m'},
      {text: '20m', value: '20m'},
      {text: '1h', value: '1h'},
      {text: '1d', value: '1d'},
    ],

    pipelineOptions: {
      'moving_avg' : [
        {text: 'window', default: 5},
        {text: 'model', default: 'simple'}
      ],
      'derivative': [
        {text: 'unit', default: undefined},
      ]
    },

    getMetricAggTypes: function(esVersion) {
      return _.filter(this.metricAggTypes, function(f) {
        if (f.minVersion) {
          return f.minVersion <= esVersion;
        } else {
          return true;
        }
      });
    },

    getPipelineOptions: function(metric) {
      if (!this.isPipelineAgg(metric.type)) {
        return [];
      }

      return this.pipelineOptions[metric.type];
    },

    isPipelineAgg: function(metricType) {
      if (metricType) {
        var po = this.pipelineOptions[metricType];
        return po !== null && po !== undefined;
      }

      return false;
    },

    getPipelineAggOptions: function(targets) {
      var self = this;
      var result = [];
      _.each(targets.metrics, function(metric) {
        if (!self.isPipelineAgg(metric.type)) {
          result.push({text: self.describeMetric(metric), value: metric.id });
        }
      });

      return result;
    },

    getOrderByOptions: function(target) {
      var self = this;
      var metricRefs = [];
      _.each(target.metrics, function(metric) {
        if (metric.type !== 'count') {
          metricRefs.push({text: self.describeMetric(metric), value: metric.id});
        }
      });

      return this.orderByOptions.concat(metricRefs);
    },

    describeOrder: function(order) {
      var def = _.find(this.orderOptions, {value: order});
      return def.text;
    },

    describeMetric: function(metric) {
      var def = _.find(this.metricAggTypes, {value: metric.type});
      return def.text + ' ' + metric.field;
    },

    describeOrderBy: function(orderBy, target) {
      var def = _.find(this.orderByOptions, {value: orderBy});
      if (def) {
        return def.text;
      }
      var metric = _.find(target.metrics, {id: orderBy});
      if (metric) {
        return this.describeMetric(metric);
      } else {
        return "metric not found";
      }
    },
  };

});
