text: /*
  
    ## Timepicker
  
    The timepicker panel is used to select time ranges and inform other panel of 
    them. It also handles searching for indices that match the given time range and 
    a pattern
  
    ### Parameters
    * mode :: The default mode of the panel. Options: 'relative', 'absolute' 'since' Default: 'relative'
    * time_options :: An array of possible time options. Default: ['5m','15m','1h','6h','12h','24h','2d','7d','30d']
    * timespan :: The default options selected for the relative view. Default: '15m'
    * timefield :: The field in which time is stored in the document.
    * index :: Index pattern to match. Literals should be double quoted. Default: '_all'
    * defaultindex :: Index to failover to if index not found
    * index_interval :: Time between timestamped indices (can be 'none') for static index
    * refresh: Object containing refresh parameters
      * enable :: true/false, enable auto refresh by default. Default: false
      * interval :: Seconds between auto refresh. Default: 30
      * min :: The lowest interval a user may set
  
    ### Group Events
    #### Sends
    * time :: Object Includes from, to and index
    #### Receives
    * get_time :: Receives an object containing a $id, broadcasts back to it.
  
  */
  
  angular.module('kibana.timepicker', [])
  .controller('timepicker', function($scope, eventBus, $timeout, timer, $http, kbnIndex) {
  
    // Set and populate defaults
    var _d = {
      mode          : "relative",
      time_options  : ['5m','15m','1h','6h','12h','24h','2d','7d','30d'],
      timespan      : '15m',
      timefield     : '@timestamp',
      index         : '_all',
      defaultindex  : "_all",
      index_interval: "none",
      timeformat    : "",
      group         : "default",
      refresh       : {
        enable  : false, 
        interval: 30,
        min     : 3
      }
    }
    _.defaults($scope.panel,_d)
  
    var _groups = _.isArray($scope.panel.group) ? 
      $scope.panel.group : [$scope.panel.group];
  
    $scope.init = function() {
      // Private refresh interval that we can use for view display without causing
      // unnecessary refreshes during changes
      $scope.refresh_interval = $scope.panel.refresh.interval
  
      // Init a private time object with Date() objects depending on mode
      switch($scope.panel.mode) {
        case 'absolute':
          $scope.time = {
            from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(time_ago($scope.panel.timespan)),
            to   : moment($scope.panel.time.to,'MM/DD/YYYY HH:mm:ss') || moment()
          }
          break;
        case 'since':
          $scope.time = {
            from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(time_ago($scope.panel.timespan)),
            to   : moment()
          }
          break;
        case 'relative':
          $scope.time = {
            from : moment(time_ago($scope.panel.timespan)),
            to   : moment()
          }
          break;
      }
      $scope.time.field = $scope.panel.timefield;
      $scope.time_apply();
  
      // Start refresh timer if enabled
      if ($scope.panel.refresh.enable)
        $scope.set_interval($scope.panel.refresh.interval);
  
      // In the case that a panel is not ready to receive a time event, it may
      // request one be sent by broadcasting a 'get_time' with its _id to its group
      // This panel can handle multiple groups
      eventBus.register($scope,"get_time", function(event,id) {
        eventBus.broadcast($scope.$id,id,'time',compile_time($scope.time))
      });
  
      // In case some other panel broadcasts a time, set us to an absolute range
      eventBus.register($scope,"set_time", function(event,time) {
        $scope.panel.mode = 'absolute';
        set_timepicker(moment(time.from),moment(time.to))
        $scope.time_apply()
      });
      
      eventBus.register($scope,"zoom", function(event,factor) {
        var _timespan = ($scope.time.to.valueOf() - $scope.time.from.valueOf());
        try {
          if($scope.panel.mode != 'absolute') {
            $scope.panel.mode = 'since'
            set_timepicker(moment($scope.time.to.valueOf() - _timespan*factor),$scope.time.to)
          } else {
            var _center = $scope.time.to.valueOf() - _timespan/2
            set_timepicker(moment(_center - (_timespan*factor)/2),
                           moment(_center + (_timespan*factor)/2))        
          }
        } catch (e) {
          console.log(e)
        }     
        $scope.time_apply();
      });
    }
  
    $scope.set_interval = function (refresh_interval) {
      $scope.panel.refresh.interval = refresh_interval
      if(_.isNumber($scope.panel.refresh.interval)) {
        if($scope.panel.refresh.interval < $scope.panel.refresh.min) {
          $scope.panel.refresh.interval = $scope.panel.refresh.min        
          timer.cancel($scope.refresh_timer)
          return;
        }
        timer.cancel($scope.refresh_timer)
        $scope.refresh()
      } else {
        timer.cancel($scope.refresh_timer)
      }
    }
  
    $scope.refresh = function() {
      if ($scope.panel.refresh.enable) {
        timer.cancel($scope.refresh_timer)
        $scope.refresh_timer = timer.register($timeout(function() {
          $scope.refresh();
          $scope.time_apply();
          },$scope.panel.refresh.interval*1000
        ));
      } else {
        timer.cancel($scope.refresh_timer)
      }
    }
  
    $scope.set_mode = function(mode) {
      $scope.panel.mode = mode;
      $scope.panel.refresh.enable = mode === 'absolute' ? 
        false : $scope.panel.refresh.enable
    }
  
    $scope.to_now = function() {
      $scope.timepicker.to = {
        time : moment().format("HH:mm:ss"),
        date : moment().format("MM/DD/YYYY")
      }
    }
  
    $scope.set_timespan = function(timespan) {
      $scope.panel.timespan = timespan;
      $scope.timepicker.from = {
        time : moment(time_ago(timespan)).format("HH:mm:ss"),
        date : moment(time_ago(timespan)).format("MM/DD/YYYY")
      }
      $scope.time_apply();
    }
  
    $scope.close_edit = function() {
      $scope.time_apply();
    }
  
    // 
    $scope.time_calc = function(){
      // If time picker is defined (usually is)
      if(!(_.isUndefined($scope.timepicker))) {
        var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) :
          moment($scope.timepicker.from.date + " " + $scope.timepicker.from.time,'MM/DD/YYYY HH:mm:ss')
        var to = $scope.panel.mode !== 'absolute' ? moment() :
          moment($scope.timepicker.to.date + " " + $scope.timepicker.to.time,'MM/DD/YYYY HH:mm:ss')
      // Otherwise (probably initialization)
      } else {
        var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) :
          $scope.time.from;
        var to = $scope.panel.mode !== 'absolute' ? moment() :
          $scope.time.to;
      }
  
      if (from.valueOf() >= to.valueOf())
        from = moment(to.valueOf() - 1000)
  
      $timeout(function(){
        set_timepicker(from,to)
      });
  
      return {
        from : from,
        to   : to
      };
    }
  
    $scope.time_apply = function() {   
      $scope.panel.error = "";   
      // Update internal time object
      $scope.time = $scope.time_calc();
      $scope.time.field = $scope.panel.timefield
  
      // Get indices for the time period, then broadcast time range and index list
      // in a single object. Not sure if I like this.
      if($scope.panel.index_interval !== 'none') {
        kbnIndex.indices($scope.time.from,
          $scope.time.to,
          $scope.panel.index,
          $scope.panel.index_interval
        ).then(function (p) {
          if(p.length > 0) {
            $scope.time.index = p;
            eventBus.broadcast($scope.$id,$scope.panel.group,'time',compile_time($scope.time))
          } else {
            $scope.panel.error = "Could not match index pattern to any ElasticSearch indices"
          }
        });
      } else {
        $scope.time.index = [$scope.panel.index];
        eventBus.broadcast($scope.$id,$scope.panel.group,'time',compile_time($scope.time))
      }
  
      // Update panel's string representation of the time object.Don't update if
      // we're in relative mode since we dont want to store the time object in the
      // json for relative periods
      if($scope.panel.mode !== 'relative') {
        $scope.panel.time = { 
          from : $scope.time.from.format("MM/DD/YYYY HH:mm:ss"),
          to : $scope.time.to.format("MM/DD/YYYY HH:mm:ss"),
          index : $scope.time.index,
        };
      } else {
        delete $scope.panel.time;
      }
    };
  
    // Prefer to pass around Date() objects in the EventBus since interacting with
    // moment objects in libraries that are expecting Date()s can be tricky
    function compile_time(time) {
      time = _.clone(time)
      time.from = time.from.toDate()
      time.to   = time.to.toDate()
      time.interval = $scope.panel.index_interval
      time.pattern = $scope.panel.index 
      return time;
    }
  
    function set_timepicker(from,to) {
      // Janky 0s timeout to get around $scope queue processing view issue
      $scope.timepicker = {
        from : {
          time : from.format("HH:mm:ss"),
          date : from.format("MM/DD/YYYY")
        },
        to : {
          time : to.format("HH:mm:ss"),
          date : to.format("MM/DD/YYYY")
        } 
      }
    }
  
  })