package org.apache.samoa.moa.evaluation;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2014 - 2015 Apache Software Foundation
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.util.ArrayList;
import java.util.HashMap;

import org.apache.samoa.moa.AbstractMOAObject;
import org.apache.samoa.moa.cluster.Clustering;
import org.apache.samoa.moa.core.DataPoint;

public abstract class MeasureCollection extends AbstractMOAObject {
  private String[] names;
  private ArrayList<Double>[] values;
  private ArrayList<Double>[] sortedValues;
  private ArrayList<String> events;

  private double[] minValue;
  private double[] maxValue;
  private double[] sumValues;
  private boolean[] enabled;
  private boolean[] corrupted;
  private double time;
  private boolean debug = true;
  private MembershipMatrix mm = null;

  private HashMap<String, Integer> map;

  private int numMeasures = 0;

  public MeasureCollection() {
    names = getNames();
    numMeasures = names.length;
    map = new HashMap<String, Integer>(numMeasures);
    for (int i = 0; i < names.length; i++) {
      map.put(names[i], i);
    }
    values = (ArrayList<Double>[]) new ArrayList[numMeasures];
    sortedValues = (ArrayList<Double>[]) new ArrayList[numMeasures];
    maxValue = new double[numMeasures];
    minValue = new double[numMeasures];
    sumValues = new double[numMeasures];
    corrupted = new boolean[numMeasures];
    enabled = getDefaultEnabled();
    time = 0;
    events = new ArrayList<String>();

    for (int i = 0; i < numMeasures; i++) {
      values[i] = new ArrayList<Double>();
      sortedValues[i] = new ArrayList<Double>();
      maxValue[i] = Double.MIN_VALUE;
      minValue[i] = Double.MAX_VALUE;
      corrupted[i] = false;
      sumValues[i] = 0.0;
    }

  }

  protected abstract String[] getNames();

  public void addValue(int index, double value) {
    if (Double.isNaN(value)) {
      if (debug)
        System.out.println("NaN for " + names[index]);
      corrupted[index] = true;
    }
    if (value < 0) {
      if (debug)
        System.out.println("Negative value for " + names[index]);
    }

    values[index].add(value);
    sumValues[index] += value;
    if (value < minValue[index])
      minValue[index] = value;
    if (value > maxValue[index])
      maxValue[index] = value;
  }

  protected void addValue(String name, double value) {
    if (map.containsKey(name)) {
      addValue(map.get(name), value);
    }
    else {
      System.out.println(name + " is not a valid measure key, no value added");
    }
  }

  // add an empty entry e.g. if evaluation crashed internally
  public void addEmptyValue(int index) {
    values[index].add(Double.NaN);
    corrupted[index] = true;
  }

  public int getNumMeasures() {
    return numMeasures;
  }

  public String getName(int index) {
    return names[index];
  }

  public double getMaxValue(int index) {
    return maxValue[index];
  }

  public double getMinValue(int index) {
    return minValue[index];
  }

  public double getLastValue(int index) {
    if (values[index].size() < 1)
      return Double.NaN;
    return values[index].get(values[index].size() - 1);
  }

  public double getMean(int index) {
    if (corrupted[index] || values[index].size() < 1)
      return Double.NaN;

    return sumValues[index] / values[index].size();
  }

  private void updateSortedValues(int index) {
    // naive implementation of insertion sort
    for (int i = sortedValues[index].size(); i < values[index].size(); i++) {
      double v = values[index].get(i);
      int insertIndex = 0;
      while (!sortedValues[index].isEmpty() && insertIndex < sortedValues[index].size()
          && v > sortedValues[index].get(insertIndex))
        insertIndex++;
      sortedValues[index].add(insertIndex, v);
    }
    // for (int i = 0; i < sortedValues[index].size(); i++) {
    // System.out.print(sortedValues[index].get(i)+" ");
    // }
    // System.out.println();
  }

  public void clean(int index) {
    sortedValues[index].clear();
  }

  public double getMedian(int index) {
    updateSortedValues(index);
    int size = sortedValues[index].size();

    if (size > 0) {
      if (size % 2 == 1)
        return sortedValues[index].get((int) (size / 2));
      else
        return (sortedValues[index].get((size - 1) / 2) + sortedValues[index].get((size - 1) / 2 + 1)) / 2.0;
    }
    return Double.NaN;
  }

  public double getLowerQuartile(int index) {
    updateSortedValues(index);
    int size = sortedValues[index].size();
    if (size > 11) {
      return sortedValues[index].get(Math.round(size * 0.25f));
    }
    return Double.NaN;
  }

  public double getUpperQuartile(int index) {
    updateSortedValues(index);
    int size = sortedValues[index].size();
    if (size > 11) {
      return sortedValues[index].get(Math.round(size * 0.75f - 1));
    }
    return Double.NaN;
  }

  public int getNumberOfValues(int index) {
    return values[index].size();
  }

  public double getValue(int index, int i) {
    if (i >= values[index].size())
      return Double.NaN;
    return values[index].get(i);
  }

  public ArrayList<Double> getAllValues(int index) {
    return values[index];
  }

  public void setEnabled(int index, boolean value) {
    enabled[index] = value;
  }

  public boolean isEnabled(int index) {
    return enabled[index];
  }

  public double getMeanRunningTime() {
    if (values[0].size() != 0)
      return (time / 10e5 / values[0].size());
    else
      return 0;
  }

  protected boolean[] getDefaultEnabled() {
    boolean[] defaults = new boolean[numMeasures];
    for (int i = 0; i < defaults.length; i++) {
      defaults[i] = true;
    }
    return defaults;
  }

  protected abstract void evaluateClustering(Clustering clustering, Clustering trueClustering,
      ArrayList<DataPoint> points) throws Exception;

  /*
   * Evaluate Clustering
   * 
   * return Time in milliseconds
   */
  public double evaluateClusteringPerformance(Clustering clustering, Clustering trueClustering,
      ArrayList<DataPoint> points) throws Exception {
    long start = System.nanoTime();
    evaluateClustering(clustering, trueClustering, points);
    long duration = System.nanoTime() - start;
    time += duration;
    duration /= 10e5;
    return duration;
  }

  public void getDescription(StringBuilder sb, int indent) {

  }

  public void addEventType(String type) {
    events.add(type);
  }

  public String getEventType(int index) {
    if (index < events.size())
      return events.get(index);
    else
      return null;
  }
}
