// 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.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;
import java.util.function.Function;

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.name();
      this.description = field.description().orElse(null);
      this.type =
          Enum.class.isAssignableFrom(field.valueType()) ? field.valueType().getSimpleName() : null;
    }
  }
}
