var Measured = require('measured')
var delegate = require('delegate')
var extend = require('extend')
var util = require ('util')
/**
 *
 * @param options  name, aggregation ('avg'|'sum'|'min'|'max'),filter1,filter2, aggregationMap {count: 'sum', min: 'min'}
 * @param spm and instance of spm-metrics-js
 * @constructor
 */
var CustomMetric = function CustomMetric (options, spm) {
  this.options = options
  this.spm = spm
  this.value = 0
  this.collection = Measured.createCollection()
  this.stats = new Measured.Gauge(function () { return this.value})
  if (!this.options.aggregationMap) {
    this.options.aggregationMap = {default: 'avg', count: 'sum', mean: 'avg', median: 'avg', currentRate: 'avg', '1MinuteRate': 'avg'}
  }
  delegate(this, this.measured)
  if (options instanceof String) {
    this.options = { name: options }
  }
  var self = this
  if (this.options.interval > 0) {
    this.tid = setInterval(function () {
      self.save()
      self.spm.send()
    }, Math.max (this.options.interval, 5000))
    this.tid.unref()
  }
}

/**
 * Sets the value of the metric (name specified in constructor/options)
 * @param value
 * @param property - to append to main metric name e.g. passinng "min" user -> user.min
 */
CustomMetric.prototype.set = function (value, property) {
  this.value = value
  var metricName = this.options.name
  if (property) {
    metricName = metricName + '.' + property
  }
  this.spm.add(metricName,
    value, this.options.aggregationMap[property || 'default'] || 'avg',
    this.options.filter1 || 'filter1',
    this.options.filter2 || 'filter2')
}

CustomMetric.prototype.save = function () {
  var m = 0
  var values = {}
  var filteredValues = {}
  if (this.stats && this.stats.toJSON) {
    m = this.stats.toJSON ()
  } else {
    throw new Error('Object has no method toJSON()')
  }
  if (!(typeof m === 'number')) {
    if (m.hasOwnProperty('meter') && m.hasOwnProperty('histogram')) {
      values = extend(values, m.histogram)
      // values = extend(values, m.meter)
    } else {
      values = m
    }
    for (var key in values) {
      if (this.options.valueFilter && this.options.valueFilter instanceof Array) {
        if (this.options.valueFilter.indexOf(key) >= 0) {
          this.set(values[key], key)
          filteredValues[key] = values[key]
        } 
      } else {
        this.set(values[key], key)
        filteredValues[key] = values[key]
      }
    }
  } else {
      values = m
      filteredValues = values
      this.set (values)
  }
  if (this.stats.reset) {
    this.stats.reset()
  }
  // make code testable
  return filteredValues
}

CustomMetric.prototype.use = function (measuredType, initValues) {
  this.usedMeasure = measuredType
  this.stats = measuredType.call(this.collection, this.options.name, initValues)
  delegate(this, this.stats)
  if (this.stats.unref) {
    this.stats.unref()
  }
  return this.stats
}

CustomMetric.prototype.meter = function () {
  return this.use(this.collection.meter)
}

CustomMetric.prototype.histogram = function () {
  return this.use(this.collection.histogram)
}

CustomMetric.prototype.timer = function () {
  return this.use(this.collection.timer)
}

CustomMetric.prototype.counter = function (initValue) {
  return this.use(this.collection.counter, {count: initValue})
}

CustomMetric.prototype.clearInterval = function () {
  if (this.tid) {
    clearInterval(this.tid)
  }
}
module.exports = CustomMetric

@@ -112,17 +112,16 @@
  require
- 
 ('util')
@@ -121,16 +121,16 @@
 'util')%0A
+
 /**%0A *%0A 
@@ -982,17 +982,16 @@
 Math.max
- 
 (this.op
@@ -1445,16 +1445,44 @@
   value,
+ this.options.aggregation %7C%7C
  this.op
@@ -1782,17 +1782,16 @@
 s.toJSON
- 
 ()%0A  %7D e
@@ -2000,18 +2000,16 @@
 togram)%0A
-  
     // v
@@ -2040,16 +2040,16 @@
 .meter)%0A
+
     %7D el
@@ -2337,17 +2337,16 @@
        %7D
- 
 %0A      %7D
@@ -2451,34 +2451,32 @@
 %0A  %7D else %7B%0A    
-  
 values = m%0A     
@@ -2470,18 +2470,16 @@
 ues = m%0A
-  
     filt
@@ -2502,26 +2502,24 @@
 ues%0A    
-  
 this.set
  (values
@@ -2510,17 +2510,16 @@
 this.set
- 
 (values)

use options.aggregation as default