// 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 static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.metrics.dropwizard.MetricResource.METRIC_KIND;
import static com.google.gerrit.server.config.ConfigResource.CONFIG_KIND;

import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.gerrit.metrics.CallbackMetric;
import com.google.gerrit.metrics.CallbackMetric0;
import com.google.gerrit.metrics.CallbackMetric1;
import com.google.gerrit.metrics.Counter0;
import com.google.gerrit.metrics.Counter1;
import com.google.gerrit.metrics.Counter2;
import com.google.gerrit.metrics.Counter3;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.FieldOrdering;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.Histogram0;
import com.google.gerrit.metrics.Histogram1;
import com.google.gerrit.metrics.Histogram2;
import com.google.gerrit.metrics.Histogram3;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.metrics.Timer2;
import com.google.gerrit.metrics.Timer3;
import com.google.gerrit.metrics.proc.JGitMetricModule;
import com.google.gerrit.metrics.proc.ProcMetricModule;
import com.google.gerrit.server.cache.CacheMetrics;
import com.google.inject.Inject;
import com.google.inject.Scopes;
import com.google.inject.Singleton;

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

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * Connects Gerrit metric package onto DropWizard.
 *
 * @see <a href="http://www.dropwizard.io/">DropWizard</a>
 */
@Singleton
public class DropWizardMetricMaker extends MetricMaker {
  public static class ApiModule extends RestApiModule {
    @Override
    protected void configure() {
      bind(MetricRegistry.class).in(Scopes.SINGLETON);
      bind(DropWizardMetricMaker.class).in(Scopes.SINGLETON);
      bind(MetricMaker.class).to(DropWizardMetricMaker.class);

      install(new ProcMetricModule());
      install(new JGitMetricModule());
    }
  }

  public static class RestModule extends RestApiModule {
    @Override
    protected void configure() {
      DynamicMap.mapOf(binder(), METRIC_KIND);
      child(CONFIG_KIND, "metrics").to(MetricsCollection.class);
      get(METRIC_KIND).to(GetMetric.class);
      bind(CacheMetrics.class);
    }
  }

  private final MetricRegistry registry;
  private final Map<String, BucketedMetric> bucketed;
  private final Map<String, ImmutableMap<String, String>> descriptions;

  @Inject
  DropWizardMetricMaker(MetricRegistry registry) {
    this.registry = registry;
    this.bucketed = new ConcurrentHashMap<>();
    this.descriptions = new ConcurrentHashMap<>();
  }

  Iterable<String> getMetricNames() {
    return descriptions.keySet();
  }

  /** Get the underlying metric implementation. */
  public Metric getMetric(String name) {
    Metric m = bucketed.get(name);
    return m != null ? m : registry.getMetrics().get(name);
  }

  /** Lookup annotations from a metric's {@link Description}. */
  public ImmutableMap<String, String> getAnnotations(String name) {
    return descriptions.get(name);
  }

  @Override
  public synchronized Counter0 newCounter(String name, Description desc) {
    checkCounterDescription(name, desc);
    define(name, desc);
    return newCounterImpl(name, desc.isRate());
  }

  @Override
  public synchronized <F1> Counter1<F1> newCounter(
      String name, Description desc,
      Field<F1> field1) {
    checkCounterDescription(name, desc);
    CounterImpl1<F1> m = new CounterImpl1<>(this, name, desc, field1);
    define(name, desc);
    bucketed.put(name, m);
    return m.counter();
  }

  @Override
  public synchronized <F1, F2> Counter2<F1, F2> newCounter(
      String name, Description desc,
      Field<F1> field1, Field<F2> field2) {
    checkCounterDescription(name, desc);
    CounterImplN m = new CounterImplN(this, name, desc, field1, field2);
    define(name, desc);
    bucketed.put(name, m);
    return m.counter2();
  }

  @Override
  public synchronized <F1, F2, F3> Counter3<F1, F2, F3> newCounter(
      String name, Description desc,
      Field<F1> field1, Field<F2> field2, Field<F3> field3) {
    checkCounterDescription(name, desc);
    CounterImplN m = new CounterImplN(this, name, desc, field1, field2, field3);
    define(name, desc);
    bucketed.put(name, m);
    return m.counter3();
  }

  private static void checkCounterDescription(String name, Description desc) {
    checkMetricName(name);
    checkArgument(!desc.isConstant(), "counters must not be constant");
    checkArgument(!desc.isGauge(), "counters must not be gauge");
  }

  CounterImpl newCounterImpl(String name, boolean isRate) {
    if (isRate) {
      final com.codahale.metrics.Meter m = registry.meter(name);
      return new CounterImpl(name, m) {
        @Override
        public void incrementBy(long delta) {
          checkArgument(delta >= 0, "counter delta must be >= 0");
          m.mark(delta);
        }
      };
    }
    final com.codahale.metrics.Counter m = registry.counter(name);
    return new CounterImpl(name, m) {
      @Override
      public void incrementBy(long delta) {
        checkArgument(delta >= 0, "counter delta must be >= 0");
        m.inc(delta);
      }
    };
  }

  @Override
  public synchronized Timer0 newTimer(String name, Description desc) {
    checkTimerDescription(name, desc);
    define(name, desc);
    return newTimerImpl(name);
  }

  @Override
  public synchronized <F1> Timer1<F1> newTimer(String name, Description desc, Field<F1> field1) {
    checkTimerDescription(name, desc);
    TimerImpl1<F1> m = new TimerImpl1<>(this, name, desc, field1);
    define(name, desc);
    bucketed.put(name, m);
    return m.timer();
  }

  @Override
  public synchronized <F1, F2> Timer2<F1, F2> newTimer(String name, Description desc,
      Field<F1> field1, Field<F2> field2) {
    checkTimerDescription(name, desc);
    TimerImplN m = new TimerImplN(this, name, desc, field1, field2);
    define(name, desc);
    bucketed.put(name, m);
    return m.timer2();
  }

  @Override
  public synchronized <F1, F2, F3> Timer3<F1, F2, F3> newTimer(
      String name, Description desc,
      Field<F1> field1, Field<F2> field2, Field<F3> field3) {
    checkTimerDescription(name, desc);
    TimerImplN m = new TimerImplN(this, name, desc, field1, field2, field3);
    define(name, desc);
    bucketed.put(name, m);
    return m.timer3();
  }

  private static void checkTimerDescription(String name, Description desc) {
    checkMetricName(name);
    checkArgument(!desc.isConstant(), "timer must not be constant");
    checkArgument(!desc.isGauge(), "timer must not be a gauge");
    checkArgument(!desc.isRate(), "timer must not be a rate");
    checkArgument(desc.isCumulative(), "timer must be cumulative");
    checkArgument(desc.getTimeUnit() != null, "timer must have a unit");
  }

  TimerImpl newTimerImpl(String name) {
    return new TimerImpl(name, registry.timer(name));
  }

  @Override
  public synchronized Histogram0 newHistogram(String name, Description desc) {
    checkHistogramDescription(name, desc);
    define(name, desc);
    return newHistogramImpl(name);
  }

  @Override
  public synchronized <F1> Histogram1<F1> newHistogram(String name,
      Description desc, Field<F1> field1) {
    checkHistogramDescription(name, desc);
    HistogramImpl1<F1> m = new HistogramImpl1<>(this, name, desc, field1);
    define(name, desc);
    bucketed.put(name, m);
    return m.histogram1();
  }

  @Override
  public synchronized <F1, F2> Histogram2<F1, F2> newHistogram(String name,
      Description desc, Field<F1> field1, Field<F2> field2) {
    checkHistogramDescription(name, desc);
    HistogramImplN m = new HistogramImplN(this, name, desc, field1, field2);
    define(name, desc);
    bucketed.put(name, m);
    return m.histogram2();
  }

  @Override
  public synchronized <F1, F2, F3> Histogram3<F1, F2, F3> newHistogram(
      String name, Description desc,
      Field<F1> field1, Field<F2> field2, Field<F3> field3) {
    checkHistogramDescription(name, desc);
    HistogramImplN m = new HistogramImplN(this, name, desc, field1, field2, field3);
    define(name, desc);
    bucketed.put(name, m);
    return m.histogram3();
  }

  private static void checkHistogramDescription(String name, Description desc) {
    checkMetricName(name);
    checkArgument(!desc.isConstant(), "histogram must not be constant");
    checkArgument(!desc.isGauge(), "histogram must not be a gauge");
    checkArgument(!desc.isRate(), "histogram must not be a rate");
    checkArgument(desc.isCumulative(), "histogram must be cumulative");
  }

  HistogramImpl newHistogramImpl(String name) {
    return new HistogramImpl(name, registry.histogram(name));
  }

  @Override
  public <V> CallbackMetric0<V> newCallbackMetric(
      String name, Class<V> valueClass, Description desc) {
    checkMetricName(name);
    define(name, desc);
    return new CallbackMetricImpl0<>(this, registry, name, valueClass);
  }

  @Override
  public <F1, V> CallbackMetric1<F1, V> newCallbackMetric(
      String name, Class<V> valueClass, Description desc, Field<F1> field1) {
    checkMetricName(name);
    CallbackMetricImpl1<F1, V> m = new CallbackMetricImpl1<>(this, registry,
        name, valueClass, desc, field1);
    define(name, desc);
    bucketed.put(name, m);
    return m.create();
  }

  @Override
  public synchronized RegistrationHandle newTrigger(
      Set<CallbackMetric<?>> metrics, Runnable trigger) {
    final ImmutableSet<CallbackMetricGlue> all = FluentIterable.from(metrics)
        .transform(
          new Function<CallbackMetric<?>, CallbackMetricGlue>() {
            @Override
            public CallbackMetricGlue apply(CallbackMetric<?> input) {
              return (CallbackMetricGlue) input;
            }
          })
        .toSet();

    trigger = new CallbackGroup(trigger, all);
    for (CallbackMetricGlue m : all) {
      m.register(trigger);
    }
    trigger.run();

    return new RegistrationHandle() {
      @Override
      public void remove() {
        for (CallbackMetricGlue m : all) {
          m.remove();
        }
      }
    };
  }

  synchronized void remove(String name) {
    bucketed.remove(name);
    descriptions.remove(name);
  }

  private synchronized void define(String name, Description desc) {
    if (descriptions.containsKey(name)) {
      ImmutableMap<String, String> annotations = descriptions.get(name);
      if (!desc.getAnnotations().get(Description.DESCRIPTION).equals(
          annotations.get(Description.DESCRIPTION))) {
        throw new IllegalStateException(String.format(
            "metric %s already defined", name));
      }
    } else {
      descriptions.put(name, desc.getAnnotations());
    }
  }

  private static final Pattern METRIC_NAME_PATTERN = Pattern
      .compile("[a-zA-Z0-9_-]+(/[a-zA-Z0-9_-]+)*");

  private static void checkMetricName(String name) {
    checkArgument(
        METRIC_NAME_PATTERN.matcher(name).matches(),
        "metric name must match %s", METRIC_NAME_PATTERN.pattern());
  }

  static String name(Description.FieldOrdering ordering,
      String codeName,
      String fieldValues) {
    if (ordering == FieldOrdering.PREFIX_FIELDS_BASENAME) {
      int s = codeName.lastIndexOf('/');
      if (s > 0) {
        String prefix = codeName.substring(0, s);
        String metric = codeName.substring(s + 1);
        return prefix + '/' + fieldValues + '/' + metric;
      }
    }
    return codeName + '/' + fieldValues;
  }

  abstract class CounterImpl extends Counter0 {
    private final String name;
    final Metric metric;

    CounterImpl(String name, Metric metric) {
      this.name = name;
      this.metric = metric;
    }

    @Override
    public void remove() {
      descriptions.remove(name);
      registry.remove(name);
    }
  }

  class TimerImpl extends Timer0 {
    private final String name;
    final com.codahale.metrics.Timer metric;

    private TimerImpl(String name, com.codahale.metrics.Timer metric) {
      this.name = name;
      this.metric = metric;
    }

    @Override
    public void record(long value, TimeUnit unit) {
      checkArgument(value >= 0, "timer delta must be >= 0");
      metric.update(value, unit);
    }

    @Override
    public void remove() {
      descriptions.remove(name);
      registry.remove(name);
    }
  }

  class HistogramImpl extends Histogram0 {
    private final String name;
    final com.codahale.metrics.Histogram metric;

    private HistogramImpl(String name, com.codahale.metrics.Histogram metric) {
      this.name = name;
      this.metric = metric;
    }

    @Override
    public void record(long value) {
      metric.update(value);
    }

    @Override
    public void remove() {
      descriptions.remove(name);
      registry.remove(name);
    }
  }
}
