package com.cloudera.server.web.cmon;

import com.cloudera.cmon.NozzleIPCWrapper.DisplayContext;
import com.cloudera.cmon.NozzleIPCWrapper.DisplayContextSummarization;
import com.cloudera.cmon.display.Column;
import com.cloudera.cmon.display.NumericMetricColumn;
import com.cloudera.cmon.firehose.MetricSelector;
import com.cloudera.cmon.firehose.nozzle.AvroMetric;
import com.cloudera.server.web.common.I18n;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;

public class JobComparisonTableModel
{
  public static final double ZERO_STDDEV_DISTANCE = 100.0D;
  static final List<Column> nonCmpColumns = Arrays.asList(new Column[] { ActivityMetricColumnSet.ID, ActivityMetricColumnSet.ACTIVITY_TYPE, ActivityMetricColumnSet.ACTIVITY_NAME, ActivityMetricColumnSet.STATUS, ActivityMetricColumnSet.START_TIME });

  static final List<NumericMetricColumn> cmpColumns = Arrays.asList(new NumericMetricColumn[] { ActivityMetricColumnSet.DURATION, ActivityMetricColumnSet.TOTAL_LAUNCHED_MAPS, ActivityMetricColumnSet.TOTAL_LAUNCHED_REDUCES, ActivityMetricColumnSet.MAP_INPUT_RECORDS, ActivityMetricColumnSet.MAP_OUTPUT_RECORDS, ActivityMetricColumnSet.REDUCE_INPUT_RECORDS, ActivityMetricColumnSet.REDUCE_OUTPUT_RECORDS, ActivityMetricColumnSet.REDUCE_INPUT_GROUPS, ActivityMetricColumnSet.REDUCE_SHUFFLE_BYTES, ActivityMetricColumnSet.SPILLED_RECORDS, ActivityMetricColumnSet.TOTAL_CPU_USER, ActivityMetricColumnSet.TOTAL_CPU_SYSTEM, ActivityMetricColumnSet.SLOTS_MILLIS_MAPS, ActivityMetricColumnSet.SLOTS_MILLIS_REDUCES, ActivityMetricColumnSet.DISK_READ, ActivityMetricColumnSet.DISK_WRITE, ActivityMetricColumnSet.HDFS_READ, ActivityMetricColumnSet.HDFS_WRITE });

  static final List<Column> allColumns = new ArrayList(nonCmpColumns);
  protected final NozzleIPCWrapper.DisplayContextSummarization contexts;
  protected final Map<String, Double> distanceMap;
  private final long serviceId;

  public JobComparisonTableModel(long serviceId, NozzleIPCWrapper.DisplayContextSummarization ctxts)
  {
    this.contexts = ctxts;
    this.serviceId = serviceId;
    this.distanceMap = new HashMap(cmpColumns.size());
    computeDistanceMap();
  }

  public List<Column> getDisplayColumns() {
    return allColumns;
  }

  public Map<String, Double> getDistanceMap()
  {
    return this.distanceMap;
  }

  private void computeDistanceMap() {
    for (NumericMetricColumn col : cmpColumns) {
      double dist = computeColumnStandardDeviation(col);
      this.distanceMap.put(col.getColumnName(), Double.valueOf(dist));
    }
  }

  private double computeColumnStandardDeviation(NumericMetricColumn col) {
    int size = this.contexts.getContexts().size();
    if (size <= 1) {
      return 0.0D;
    }

    MetricSelector selector = col.getMetricSelector();
    DescriptiveStatistics dstats = new DescriptiveStatistics();

    for (NozzleIPCWrapper.DisplayContext ctx : this.contexts.getContexts().subList(1, size)) {
      AvroMetric metric = ctx.getMetric(selector.getMetricID());
      if (metric != null) {
        dstats.addValue(selector.getMetricValueAsDouble(metric).doubleValue());
      }

    }

    NozzleIPCWrapper.DisplayContext subject = (NozzleIPCWrapper.DisplayContext)this.contexts.getContexts().get(0);
    AvroMetric metric = subject.getMetric(selector.getMetricID());
    if (metric == null) {
      return 0.0D;
    }

    double stddev = dstats.getStandardDeviation();
    double value = selector.getMetricValueAsDouble(metric).doubleValue();
    double mean = dstats.getMean();
    if (stddev == 0.0D) {
      if (value == mean) {
        return 0.0D;
      }
      return value > mean ? 100.0D : -100.0D;
    }
    return (value - mean) / stddev;
  }

  public NozzleIPCWrapper.DisplayContextSummarization getDisplayContexts()
  {
    return this.contexts;
  }

  public String getPageTitle()
  {
    List allDisplayColumns = getDisplayColumns();
    List ctxs = getDisplayContexts().getContexts();
    String currentActivity = "";
    if ((!ctxs.isEmpty()) && (!allDisplayColumns.isEmpty())) {
      currentActivity = ((Column)allDisplayColumns.get(0)).getDisplayValue((NozzleIPCWrapper.DisplayContext)ctxs.get(0));
    }
    return I18n.t("label.similarActivitiesOf", new String[] { currentActivity });
  }

  public long getServiceId() {
    return this.serviceId;
  }

  static
  {
    allColumns.addAll(cmpColumns);
  }
}