// 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;

import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import java.util.Set;

/** Factory to create metrics for monitoring. */
public abstract class MetricMaker {
  /**
   * Metric whose value increments during the life of the process.
   *
   * @param name field name
   * @param desc field description
   * @return counter
   */
  public abstract Counter0 newCounter(String name, Description desc);

  public abstract <F1> Counter1<F1> newCounter(String name, Description desc, Field<F1> field1);

  public abstract <F1, F2> Counter2<F1, F2> newCounter(
      String name, Description desc, Field<F1> field1, Field<F2> field2);

  public abstract <F1, F2, F3> Counter3<F1, F2, F3> newCounter(
      String name, Description desc, Field<F1> field1, Field<F2> field2, Field<F3> field3);

  /**
   * Metric recording time spent on an operation.
   *
   * @param name field name
   * @param desc field description
   * @return timer
   */
  public abstract Timer0 newTimer(String name, Description desc);

  public abstract <F1> Timer1<F1> newTimer(String name, Description desc, Field<F1> field1);

  public abstract <F1, F2> Timer2<F1, F2> newTimer(
      String name, Description desc, Field<F1> field1, Field<F2> field2);

  public abstract <F1, F2, F3> Timer3<F1, F2, F3> newTimer(
      String name, Description desc, Field<F1> field1, Field<F2> field2, Field<F3> field3);

  /**
   * Metric recording statistical distribution of values.
   *
   * @param name field name
   * @param desc field description
   * @return histogram
   */
  public abstract Histogram0 newHistogram(String name, Description desc);

  public abstract <F1> Histogram1<F1> newHistogram(String name, Description desc, Field<F1> field1);

  public abstract <F1, F2> Histogram2<F1, F2> newHistogram(
      String name, Description desc, Field<F1> field1, Field<F2> field2);

  public abstract <F1, F2, F3> Histogram3<F1, F2, F3> newHistogram(
      String name, Description desc, Field<F1> field1, Field<F2> field2, Field<F3> field3);

  /**
   * Constant value that does not change.
   *
   * @param name unique name of the metric.
   * @param value only value of the metric.
   * @param desc description of the metric.
   */
  public <V> void newConstantMetric(String name, V value, Description desc) {
    desc.setConstant();

    @SuppressWarnings("unchecked")
    Class<V> type = (Class<V>) value.getClass();
    CallbackMetric0<V> metric = newCallbackMetric(name, type, desc);
    newTrigger(metric, () -> metric.set(value));
  }

  /**
   * Instantaneous reading of a value.
   *
   * <pre>
   * metricMaker.newCallbackMetric(&quot;memory&quot;,
   *     new Description(&quot;Total bytes of memory used&quot;)
   *        .setGauge()
   *        .setUnit(Units.BYTES),
   *     new Supplier&lt;Long&gt;() {
   *       public Long get() {
   *         return Runtime.getRuntime().totalMemory();
   *       }
   *     });
   * </pre>
   *
   * @param name unique name of the metric.
   * @param valueClass type of value recorded by the metric.
   * @param desc description of the metric.
   * @param trigger function to compute the value of the metric.
   */
  public <V> void newCallbackMetric(
      String name, Class<V> valueClass, Description desc, Supplier<V> trigger) {
    CallbackMetric0<V> metric = newCallbackMetric(name, valueClass, desc);
    newTrigger(metric, () -> metric.set(trigger.get()));
  }

  /**
   * Instantaneous reading of a single value.
   *
   * @param name field name
   * @param valueClass field type
   * @param desc field description
   * @return callback
   */
  public abstract <V> CallbackMetric0<V> newCallbackMetric(
      String name, Class<V> valueClass, Description desc);

  public abstract <F1, V> CallbackMetric1<F1, V> newCallbackMetric(
      String name, Class<V> valueClass, Description desc, Field<F1> field1);

  /**
   * Connect logic to populate a previously created {@link CallbackMetric}.
   *
   * @param metric1 previously created callback
   * @param trigger trigger to connect
   * @return registration handle
   */
  public RegistrationHandle newTrigger(CallbackMetric<?> metric1, Runnable trigger) {
    return newTrigger(ImmutableSet.of(metric1), trigger);
  }

  public RegistrationHandle newTrigger(
      CallbackMetric<?> metric1, CallbackMetric<?> metric2, Runnable trigger) {
    return newTrigger(ImmutableSet.of(metric1, metric2), trigger);
  }

  public RegistrationHandle newTrigger(
      CallbackMetric<?> metric1,
      CallbackMetric<?> metric2,
      CallbackMetric<?> metric3,
      Runnable trigger) {
    return newTrigger(ImmutableSet.of(metric1, metric2, metric3), trigger);
  }

  public abstract RegistrationHandle newTrigger(Set<CallbackMetric<?>> metrics, Runnable trigger);

  /**
   * Sanitize the given metric name.
   *
   * @param name the name to sanitize.
   * @return sanitized version of the name.
   */
  public String sanitizeMetricName(String name) {
    return name;
  }
}
