/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package d.climate.dssat;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author sidereus
 */
public class LongTermAverage {

  private Map<Integer, MinMaxAvg> dataCollect;
  private Double longTermAvg = null;
  private Double amplitude = null;

  public LongTermAverage() {
    dataCollect = new HashMap();
  }

  public void add(int month, double minvalue, double maxvalue) {
    MinMaxAvg monthlyData;
    if (dataCollect.containsKey(month)) {
      monthlyData = dataCollect.get(month);
      monthlyData.add(minvalue, maxvalue);
    } else {
      monthlyData = new MinMaxAvg(minvalue, maxvalue);
    }
    dataCollect.put(month, monthlyData);
  }

  private void compute() {

    double sum_monthlyAvg = 0.0;
    double max_monthlyAvg = Double.MIN_VALUE;
    double min_monthlyAvg = Double.MAX_VALUE;
    int numMonths = dataCollect.values().size();

    for (MinMaxAvg monthlyData : dataCollect.values()) {
      double monthlyAvg = monthlyData.getAvg();
      sum_monthlyAvg += monthlyAvg;

      if (monthlyAvg < min_monthlyAvg) {
        min_monthlyAvg = monthlyAvg;
      }
      if (monthlyAvg > max_monthlyAvg) {
        max_monthlyAvg = monthlyAvg;
      }
    }

    longTermAvg = sum_monthlyAvg / numMonths;
    amplitude = (max_monthlyAvg - min_monthlyAvg) / 2;

  }

  public Double getLongTermAvg() {
    checkDataCollectAndCompute(longTermAvg);
    return longTermAvg;
  }

  public Double getAmplitude() {
    checkDataCollectAndCompute(amplitude);
    return amplitude;
  }

  private void checkDataCollectAndCompute(Double variable) {
    if (dataCollect.isEmpty()) {
      throw new NullPointerException("Datacollect is empty");
    }

    if (variable == null) {
      compute();
    }
  }

  private class MinMaxAvg {

    private double minvalue = 0.0;
    private double maxvalue = 0.0;
    private int count = 0;

    MinMaxAvg(double minvalue, double maxvalue) {
      this.minvalue = minvalue;
      this.maxvalue = maxvalue;
      this.count += 1;
    }

    public void add(double minvalue, double maxvalue) {
      this.minvalue += minvalue;
      this.maxvalue += maxvalue;
      this.count += 1;
    }

    private double getMinAvg() {
      return minvalue / count;
    }

    private double getMaxAvg() {
      return maxvalue / count;
    }

    public double getAvg() {
      return (getMaxAvg() + getMinAvg()) / 2;
    }
  }

}
