// Copyright 2020 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.actions;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.time.Duration;
import java.util.EnumMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.ToLongFunction;
import javax.annotation.Nullable;

/** Metrics aggregated per execution kind. */
public final class AggregatedSpawnMetrics {

  public static final AggregatedSpawnMetrics EMPTY = new AggregatedSpawnMetrics(ImmutableMap.of());

  /** Static holder for lazy initialization. */
  private static class EmptyMetrics {
    /**
     * Map with empty {@link SpawnMetrics}.
     *
     * <p>This is useful for {@link #getMetrics(SpawnMetrics.ExecKind)} where we need to return an
     * empty {@link SpawnMetrics} with the correct {@link SpawnMetrics.ExecKind}.
     */
    private static final ImmutableMap<SpawnMetrics.ExecKind, SpawnMetrics> INSTANCE =
        createEmptyMetrics();

    private static final ImmutableMap<SpawnMetrics.ExecKind, SpawnMetrics> createEmptyMetrics() {
      EnumMap<SpawnMetrics.ExecKind, SpawnMetrics> map = new EnumMap<>(SpawnMetrics.ExecKind.class);
      for (SpawnMetrics.ExecKind kind : SpawnMetrics.ExecKind.values()) {
        map.put(kind, SpawnMetrics.Builder.forExec(kind).build());
      }
      return Maps.immutableEnumMap(map);
    }
  }

  private final ImmutableMap<SpawnMetrics.ExecKind, SpawnMetrics> metricsMap;

  private AggregatedSpawnMetrics(ImmutableMap<SpawnMetrics.ExecKind, SpawnMetrics> metricsMap) {
    this.metricsMap = metricsMap;
  }

  /**
   * Returns all present {@link SpawnMetrics}.
   *
   * <p>There will be at most one {@link SpawnMetrics} object per {@link SpawnMetrics.ExecKind}.
   */
  public ImmutableCollection<SpawnMetrics> getAllMetrics() {
    return metricsMap.values();
  }

  /**
   * Returns {@link SpawnMetrics} for the provided execution kind.
   *
   * <p>This will never return {@code null}, but the {@link SpawnMetrics} can be empty.
   */
  public SpawnMetrics getMetrics(SpawnMetrics.ExecKind kind) {
    @Nullable SpawnMetrics metrics = metricsMap.get(kind);
    if (metrics == null) {
      return EmptyMetrics.INSTANCE.get(kind);
    }
    return metrics;
  }

  /**
   * Returns {@link SpawnMetrics} for the remote execution.
   *
   * @see #getMetrics(SpawnMetrics.ExecKind)
   */
  public SpawnMetrics getRemoteMetrics() {
    return getMetrics(SpawnMetrics.ExecKind.REMOTE);
  }

  /**
   * Returns a new {@link AggregatedSpawnMetrics} that incorporates the provided metrics by summing
   * them with the existing ones (if any).
   */
  public AggregatedSpawnMetrics sumAllMetrics(SpawnMetrics other) {
    SpawnMetrics existing = getMetrics(other.execKind());
    SpawnMetrics.Builder builder =
        SpawnMetrics.Builder.forExec(other.execKind())
            .addDurations(existing)
            .addDurations(other)
            .addNonDurations(existing)
            .addNonDurations(other);

    EnumMap<SpawnMetrics.ExecKind, SpawnMetrics> map = new EnumMap<>(SpawnMetrics.ExecKind.class);
    map.putAll(metricsMap);
    map.put(other.execKind(), builder.build());
    return new AggregatedSpawnMetrics(Maps.immutableEnumMap(map));
  }

  /**
   * Returns a new {@link AggregatedSpawnMetrics} that incorporates the provided metrics by summing
   * the duration ones and taking the maximum for the non-duration ones.
   */
  public AggregatedSpawnMetrics sumDurationsMaxOther(SpawnMetrics other) {
    SpawnMetrics existing = getMetrics(other.execKind());
    SpawnMetrics.Builder builder =
        SpawnMetrics.Builder.forExec(other.execKind())
            .addDurations(existing)
            .addDurations(other)
            .maxNonDurations(existing)
            .maxNonDurations(other);

    EnumMap<SpawnMetrics.ExecKind, SpawnMetrics> map = new EnumMap<>(SpawnMetrics.ExecKind.class);
    map.putAll(metricsMap);
    map.put(other.execKind(), builder.build());
    return new AggregatedSpawnMetrics(Maps.immutableEnumMap(map));
  }

  /**
   * Returns the total duration across all execution kinds.
   *
   * <p>Example: {@code getTotalDuration(SpawnMetrics::queueTime)} will give the total queue time
   * across all execution kinds.
   */
  public Duration getTotalDuration(Function<SpawnMetrics, Duration> extract) {
    Duration result = Duration.ZERO;
    for (SpawnMetrics metric : metricsMap.values()) {
      result = result.plus(extract.apply(metric));
    }
    return result;
  }

  /**
   * Returns the maximum value of a non-duration metric across all execution kinds.
   *
   * <p>Example: {@code getMaxNonDuration(0, SpawnMetrics::inputFiles)} returns the maximum number
   * of input files across all the execution kinds.
   */
  public long getMaxNonDuration(long initialValue, ToLongFunction<SpawnMetrics> extract) {
    long result = initialValue;
    for (SpawnMetrics metric : metricsMap.values()) {
      result = Long.max(result, extract.applyAsLong(metric));
    }
    return result;
  }

  public String toString(Duration total, boolean summary) {
    // For now keep compatibility with the old output and only report the remote execution.
    // TODO(michalt): Change this once the local and worker executions populate more metrics.
    return SpawnMetrics.ExecKind.REMOTE + " " + getRemoteMetrics().toString(total, summary);
  }

  /** Builder for {@link AggregatedSpawnMetrics}. */
  public static class Builder {

    private final EnumMap<SpawnMetrics.ExecKind, SpawnMetrics.Builder> builderMap =
        new EnumMap<>(SpawnMetrics.ExecKind.class);

    public AggregatedSpawnMetrics build() {
      EnumMap<SpawnMetrics.ExecKind, SpawnMetrics> map = new EnumMap<>(SpawnMetrics.ExecKind.class);
      for (Map.Entry<SpawnMetrics.ExecKind, SpawnMetrics.Builder> entry : builderMap.entrySet()) {
        map.put(entry.getKey(), entry.getValue().build());
      }
      return new AggregatedSpawnMetrics(Maps.immutableEnumMap(map));
    }

    @CanIgnoreReturnValue
    public Builder addDurations(SpawnMetrics metrics) {
      getBuilder(metrics.execKind()).addDurations(metrics);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addDurations(AggregatedSpawnMetrics aggregated) {
      aggregated.getAllMetrics().forEach(this::addDurations);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addNonDurations(SpawnMetrics metrics) {
      getBuilder(metrics.execKind()).addNonDurations(metrics);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addNonDurations(AggregatedSpawnMetrics aggregated) {
      aggregated.getAllMetrics().forEach(this::addNonDurations);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder maxNonDurations(SpawnMetrics metrics) {
      getBuilder(metrics.execKind()).maxNonDurations(metrics);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder maxNonDurations(AggregatedSpawnMetrics aggregated) {
      aggregated.getAllMetrics().forEach(this::maxNonDurations);
      return this;
    }

    private SpawnMetrics.Builder getBuilder(SpawnMetrics.ExecKind kind) {
      return builderMap.computeIfAbsent(kind, SpawnMetrics.Builder::forExec);
    }
  }
}
