module Odometer::Taker

  PRETTY_NAME = "collect their"
  FIELDS = [ 
    { type: "attribute_select", name: "attribute" }, 
    { type: "label", value: "and calculate the" },
    { type: "select", name: "action", options: [ "sum", "mean" ] }
  ]
  
  ## REQUIRED
  
  def taker_aggregator
    result = map_reduce(
        send("taker_map"), 
        send("#{ aggregator_fields['action'] }_reduce")).
      find("_id" => taker_cache_path).first
    if result
      result["value"].to_f
    else
      aggregator_fields["action"] == "mean" ? 0.0/0.0 : 0.0
    end
  end
  
  def taker_to_english
    start_the_sentence
  	@sentence += [
  	  aggregator_fields["action"],
  	  aggregator_fields["attribute"].gsub("_", " "),
  	  "of all",
  	  model.downcase.pluralize
	  ]
  	finish_the_sentence
  end
  
  def taker_cache_path
    "#{ model.tableize }_#{ aggregator_fields['attribute'] }"
  end
  
  ## END REQUIRED

  def taker_map
    <<-EOS
      function() {
        emit('#{ taker_cache_path }', this.#{ aggregator_fields['attribute'] });
      }
    EOS
  end

  def sum_reduce
    <<-EOS
      function(key, values) {
        var sum = 0;
        values.forEach(function(val) { sum += val; });
        return sum;
      }
    EOS
  end

  def mean_reduce
    <<-EOS
      function(key, values) {
        var sum = 0;
        values.forEach(function(val) { sum += val; });
        return sum / values.length;
      }
    EOS
  end

end

