// Copyright (C) 2015 The Android Open Source Project
//
// 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.

package com.google.gerrit.metrics.dropwizard;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.Metric;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.Timer;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

class MetricJson {
  String description;
  String unit;
  Boolean constant;
  Boolean rate;
  Boolean gauge;
  Boolean cumulative;

  Long count;
  Object value;

  Double rate_1m;
  Double rate_5m;
  Double rate_15m;
  Double rate_mean;

  Double p50;
  Double p75;
  Double p95;
  Double p98;
  Double p99;
  Double p99_9;

  Double min;
  Double avg;
  Double max;
  Double sum;
  Double std_dev;

  List<FieldJson> fields;
  Map<String, Object> buckets;

  MetricJson(Metric metric, ImmutableMap<String, String> atts, boolean dataOnly) {
    if (!dataOnly) {
      description = atts.get(Description.DESCRIPTION);
      unit = atts.get(Description.UNIT);
      constant = toBool(atts, Description.CONSTANT);
      rate = toBool(atts, Description.RATE);
      gauge = toBool(atts, Description.GAUGE);
      cumulative = toBool(atts, Description.CUMULATIVE);
    }
    init(metric, atts);
  }

  private void init(Metric metric, ImmutableMap<String, String> atts) {
    if (metric instanceof BucketedMetric) {
      BucketedMetric m = (BucketedMetric) metric;
      if (m.getTotal() != null) {
        init(m.getTotal(), atts);
      }

      Field<?>[] fieldList = m.getFields();
      fields = new ArrayList<>(fieldList.length);
      for (Field<?> f : fieldList) {
        fields.add(new FieldJson(f));
      }
      buckets = makeBuckets(fieldList, m.getCells(), atts);

    } else if (metric instanceof Counter) {
      Counter c = (Counter) metric;
      count = c.getCount();

    } else if (metric instanceof Gauge) {
      Gauge<?> g = (Gauge<?>) metric;
      value = g.getValue();

    } else if (metric instanceof Meter) {
      Meter m = (Meter) metric;
      count = m.getCount();
      rate_1m = m.getOneMinuteRate();
      rate_5m = m.getFiveMinuteRate();
      rate_15m = m.getFifteenMinuteRate();

    } else if (metric instanceof Timer) {
      Timer m = (Timer) metric;
      Snapshot s = m.getSnapshot();
      count = m.getCount();
      rate_1m = m.getOneMinuteRate();
      rate_5m = m.getFiveMinuteRate();
      rate_15m = m.getFifteenMinuteRate();

      double div = Description.getTimeUnit(atts.get(Description.UNIT)).toNanos(1);
      p50 = s.getMedian() / div;
      p75 = s.get75thPercentile() / div;
      p95 = s.get95thPercentile() / div;
      p98 = s.get98thPercentile() / div;
      p99 = s.get99thPercentile() / div;
      p99_9 = s.get999thPercentile() / div;

      min = s.getMin() / div;
      max = s.getMax() / div;
      std_dev = s.getStdDev() / div;

    } else if (metric instanceof Histogram) {
      Histogram m = (Histogram) metric;
      Snapshot s = m.getSnapshot();
      count = m.getCount();

      p50 = s.getMedian();
      p75 = s.get75thPercentile();
      p95 = s.get95thPercentile();
      p98 = s.get98thPercentile();
      p99 = s.get99thPercentile();
      p99_9 = s.get999thPercentile();

      min = (double) s.getMin();
      avg = s.getMean();
      max = (double) s.getMax();
      sum = s.getMean() * m.getCount();
      std_dev = s.getStdDev();
    }
  }

  private static Boolean toBool(ImmutableMap<String, String> atts, String key) {
    return Description.TRUE_VALUE.equals(atts.get(key)) ? true : null;
  }

  @SuppressWarnings("unchecked")
  private static Map<String, Object> makeBuckets(
      Field<?>[] fields, Map<?, Metric> metrics, ImmutableMap<String, String> atts) {
    if (fields.length == 1) {
      Function<Object, String> fmt = (Function<Object, String>) fields[0].formatter();
      Map<String, Object> out = new TreeMap<>();
      for (Map.Entry<?, Metric> e : metrics.entrySet()) {
        out.put(fmt.apply(e.getKey()), new MetricJson(e.getValue(), atts, true));
      }
      return out;
    }

    Map<String, Object> out = new TreeMap<>();
    for (Map.Entry<?, Metric> e : metrics.entrySet()) {
      ImmutableList<Object> keys = (ImmutableList<Object>) e.getKey();
      Map<String, Object> dst = out;

      for (int i = 0; i < fields.length - 1; i++) {
        Function<Object, String> fmt = (Function<Object, String>) fields[i].formatter();
        String key = fmt.apply(keys.get(i));
        Map<String, Object> t = (Map<String, Object>) dst.get(key);
        if (t == null) {
          t = new TreeMap<>();
          dst.put(key, t);
        }
        dst = t;
      }

      Function<Object, String> fmt =
          (Function<Object, String>) fields[fields.length - 1].formatter();
      dst.put(fmt.apply(keys.get(fields.length - 1)), new MetricJson(e.getValue(), atts, true));
    }
    return out;
  }

  static class FieldJson {
    String name;
    String type;
    String description;

    FieldJson(Field<?> field) {
      this.name = field.getName();
      this.description = field.getDescription();
      this.type =
          Enum.class.isAssignableFrom(field.getType()) ? field.getType().getSimpleName() : null;
    }
  }
}
