text: define([
    'angular',
    'lodash',
    'config'
  ],
  function (angular, _, config) {
    'use strict';
  
    var module = angular.module('grafana.controllers');
  
    module.controller('MetricKeysCtrl', function($scope, $http, $q) {
      var elasticSearchUrlForMetricIndex = config.elasticsearch + '/' + config.grafana_metrics_index + '/';
      var httpOptions = {};
      if (config.elasticsearchBasicAuth) {
        httpOptions.withCredentials = true;
        httpOptions.headers = {
          "Authorization": "Basic " + config.elasticsearchBasicAuth
        };
      }
      $scope.init = function () {
        $scope.metricPath = "prod.apps.api.boobarella.*";
        $scope.metricCounter = 0;
      };
  
      $scope.createIndex = function () {
        $scope.errorText = null;
        $scope.infoText = null;
  
        deleteIndex()
          .then(createIndex)
          .then(function () {
            $scope.infoText = "Index created!";
          })
          .then(null, function (err) {
            $scope.errorText = angular.toJson(err);
          });
      };
  
      $scope.loadMetricsFromPath = function() {
        $scope.errorText = null;
        $scope.infoText = null;
        $scope.metricCounter = 0;
  
        return loadMetricsRecursive($scope.metricPath)
          .then(function() {
            $scope.infoText = "Indexing completed!";
          }, function(err) {
            $scope.errorText = "Error: " + err;
          });
      };
  
      $scope.loadAll = function() {
        $scope.infoText = "Fetching all metrics from graphite...";
  
        getFromEachGraphite('/metrics/index.json', saveMetricsArray)
          .then(function() {
            $scope.infoText = "Indexing complete!";
          }).then(null, function(err) {
            $scope.errorText = err;
          });
      };
  
      function getFromEachGraphite(request, data_callback, error_callback) {
        return $q.all(_.map(config.datasources, function(datasource) {
          if (datasource.type = 'graphite') {
            return $http.get(datasource.url + request)
              .then(data_callback, error_callback);
          }
        }));
      }
  
      function saveMetricsArray(data, currentIndex) {
        if (!data && !data.data && data.data.length === 0) {
          return $q.reject('No metrics from graphite');
        }
  
        if (data.data.length === currentIndex) {
          return $q.when('done');
        }
  
        currentIndex = currentIndex || 0;
  
        return saveMetricKey(data.data[currentIndex])
          .then(function() {
            return saveMetricsArray(data, currentIndex + 1);
          });
      }
  
      function deleteIndex()
      {
        var deferred = $q.defer();
        $http.delete(elasticSearchUrlForMetricIndex, httpOptions)
          .success(function() {
            deferred.resolve('ok');
          })
          .error(function(data, status) {
            if (status === 404) {
              deferred.resolve('ok');
            }
            else {
              deferred.reject('elastic search returned unexpected error');
            }
          });
  
        return deferred.promise;
      }
  
      function createIndex()
      {
        return $http.put(elasticSearchUrlForMetricIndex, {
          settings: {
            analysis: {
              analyzer: {
                metric_path_ngram : { tokenizer : "my_ngram_tokenizer" }
              },
              tokenizer: {
                my_ngram_tokenizer : {
                  type : "nGram",
                  min_gram : "3",
                  max_gram : "8",
                  token_chars: ["letter", "digit", "punctuation", "symbol"]
                }
              }
            }
          },
          mappings: {
            metricKey: {
              properties: {
                metricPath: {
                  type: "multi_field",
                  fields: {
                    "metricPath": { type: "string", index: "analyzed", index_analyzer: "standard" },
                    "metricPath_ng": { type: "string", index: "analyzed", index_analyzer: "metric_path_ngram" }
                  }
                }
              }
            }
          }
        }, httpOptions);
      }
  
      function receiveMetric(result) {
        var data = result.data;
        if (!data || data.length === 0) {
          console.log('no data');
          return;
        }
  
        var funcs = _.map(data, function(metric) {
          if (metric.expandable) {
            return loadMetricsRecursive(metric.id + ".*");
          }
          if (metric.leaf) {
            return saveMetricKey(metric.id);
          }
        });
  
        return $q.all(funcs);
      }
  
      function saveMetricKey(metricId) {
  
        // Create request with id as title. Rethink this.
        var request = $scope.ejs.Document(config.grafana_metrics_index, 'metricKey', metricId).source({
          metricPath: metricId
        });
  
        return request.doIndex(
          function() {
            $scope.infoText = "Indexing " + metricId;
            $scope.metricCounter = $scope.metricCounter + 1;
          },
          function() {
            $scope.errorText = "failed to save metric " + metricId;
          }
        );
      }
  
      function loadMetricsRecursive(metricPath)
      {
        return getFromEachGraphite('/metrics/find/?query=' + metricPath, receiveMetric);
      }
  
    });
  
  });
  