// 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.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/** Abstract callback metric broken down into buckets. */
abstract class BucketedCallback<V> implements BucketedMetric {
  private final DropWizardMetricMaker metrics;
  private final MetricRegistry registry;
  private final String name;
  private final Description.FieldOrdering ordering;
  protected final Field<?>[] fields;
  private final V zero;
  private final Map<Object, ValueGauge> cells;
  protected volatile Runnable trigger;
  private final Object lock = new Object();

  BucketedCallback(DropWizardMetricMaker metrics, MetricRegistry registry,
      String name, Class<V> valueType, Description desc, Field<?>... fields) {
    this.metrics = metrics;
    this.registry = registry;
    this.name = name;
    this.ordering = desc.getFieldOrdering();
    this.fields = fields;
    this.zero = CallbackMetricImpl0.zeroFor(valueType);
    this.cells = new ConcurrentHashMap<>();
  }

  void doRemove() {
    for (Object key : cells.keySet()) {
      registry.remove(submetric(key));
    }
    metrics.remove(name);
  }

  void doBeginSet() {
    for (ValueGauge g : cells.values()) {
      g.set = false;
    }
  }

  void doPrune() {
    Iterator<Map.Entry<Object, ValueGauge>> i = cells.entrySet().iterator();
    while (i.hasNext()) {
      if (!i.next().getValue().set) {
        i.remove();
      }
    }
  }

  void doEndSet() {
    for (ValueGauge g : cells.values()) {
      if (!g.set) {
        g.value = zero;
      }
    }
  }

  ValueGauge getOrCreate(Object f1, Object f2) {
    return getOrCreate(ImmutableList.of(f1, f2));
  }

  ValueGauge getOrCreate(Object f1, Object f2, Object f3) {
    return getOrCreate(ImmutableList.of(f1, f2, f3));
  }

  ValueGauge getOrCreate(Object key) {
    ValueGauge c = cells.get(key);
    if (c != null) {
      return c;
    }

    synchronized (lock) {
      c = cells.get(key);
      if (c == null) {
        c = new ValueGauge();
        registry.register(submetric(key), c);
        cells.put(key, c);
      }
      return c;
    }
  }

  private String submetric(Object key) {
    return DropWizardMetricMaker.name(ordering, name, name(key));
  }

  abstract String name(Object key);

  @Override
  public Metric getTotal() {
    return null;
  }

  @Override
  public Field<?>[] getFields() {
    return fields;
  }

  @Override
  public Map<Object, Metric> getCells() {
    return Maps.transformValues(
        cells,
        new Function<ValueGauge, Metric> () {
          @Override
          public Metric apply(ValueGauge in) {
            return in;
          }
        });
  }

  final class ValueGauge implements Gauge<V> {
    volatile V value = zero;
    boolean set;

    @Override
    public V getValue() {
      Runnable t = trigger;
      if (t != null) {
        t.run();
      }
      return value;
    }
  }
}
