// Copyright 2015 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.profiler.statistics;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterators;
import com.google.devtools.build.lib.profiler.ProfilePhase;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo.AggregateAttr;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo.Task;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;

/**
 * Extracts and keeps statistics for one {@link ProfilePhase} for formatting to various outputs.
 */
public final class PhaseStatistics implements Iterable<ProfilerTask> {

  private final ProfilePhase phase;
  private long phaseDurationNanos;
  private long totalDurationNanos;
  private final EnumMap<ProfilerTask, Long> taskDurations;
  private final EnumMap<ProfilerTask, Long> taskCounts;
  private boolean wasExecuted;

  public PhaseStatistics(ProfilePhase phase) {
    this.phase = phase;
    this.taskDurations = new EnumMap<>(ProfilerTask.class);
    this.taskCounts = new EnumMap<>(ProfilerTask.class);
  }

  public PhaseStatistics(ProfilePhase phase, ProfileInfo info) {
    this(phase);
    addProfileInfo(info);
  }

  /** Add statistics from {@link ProfileInfo} to the ones already accumulated for this phase. */
  public void addProfileInfo(ProfileInfo info) {
    Task phaseTask = info.getPhaseTask(phase);
    if (phaseTask != null) {
      wasExecuted = true;
      long infoPhaseDuration = info.getPhaseDuration(phaseTask);
      phaseDurationNanos += infoPhaseDuration;
      List<Task> taskList = info.getTasksForPhase(phaseTask);
      long duration = infoPhaseDuration;
      for (Task task : taskList) {
        // Tasks on the phaseTask thread already accounted for in the phaseDuration.
        if (task.threadId != phaseTask.threadId) {
          duration += task.durationNanos;
        }
      }
      totalDurationNanos += duration;
      for (ProfilerTask type : ProfilerTask.values()) {
        AggregateAttr attr = info.getStatsForType(type, taskList);
        long totalTime = Math.max(0, attr.totalTime);
        long count = Math.max(0, attr.count);
        add(taskCounts, type, count);
        add(taskDurations, type, totalTime);
      }
    }
  }

  /** Helper method to sum up long values within an {@link EnumMap}. */
  private static <T extends Enum<T>> void add(EnumMap<T, Long> map, T key, long value) {
    long previous;
    if (map.containsKey(key)) {
      previous = map.get(key);
    } else {
      previous = 0;
    }
    map.put(key, previous + value);
  }

  public ProfilePhase getProfilePhase() {
    return phase;
  }

  /**
   * @return true if no {@link ProfilerTask}s have been executed in this phase, false otherwise
   */
  public boolean isEmpty() {
    return taskCounts.isEmpty();
  }

  /** @return true if the phase was not executed at all, false otherwise */
  public boolean wasExecuted() {
    return wasExecuted;
  }

  /** @return true if a task of the given {@link ProfilerTask} type was executed in this phase */
  public boolean wasExecuted(ProfilerTask taskType) {
    Long count = taskCounts.get(taskType);
    return count != null && count != 0;
  }

  public long getPhaseDurationNanos() {
    return phaseDurationNanos;
  }

  /** @return the sum of all task durations of the given type */
  public long getTotalDurationNanos(ProfilerTask taskType) {
    Long duration = taskDurations.get(taskType);
    if (duration == null) {
      return 0;
    }
    return duration;
  }

  /**
   * @return the average duration of all {@link ProfilerTask}
   */
  public double getMeanDuration(ProfilerTask taskType) {
    if (wasExecuted(taskType)) {
      double duration = taskDurations.get(taskType);
      long count = taskCounts.get(taskType);
      return duration / count;
    }
    return 0;
  }

  /**
   * @return the duration of all {@link ProfilerTask} executed in the phase relative to the total
   *    phase duration
   */
  public double getTotalRelativeDuration(ProfilerTask taskType) {
    Long duration = taskDurations.get(taskType);
    if (duration == null || duration == 0) {
      return 0;
    }
    // sanity check for broken profile files
    Preconditions.checkState(
        totalDurationNanos != 0,
        "Profiler tasks of type %s have non-zero duration %s in phase %s but the phase itself has"
        + " zero duration. Most likely the profile file is broken.",
        taskType,
        duration,
        phase);
    return (double) duration / totalDurationNanos;
  }

  /**
   * @return how many tasks of the given type were executed in this phase
   */
  public long getCount(ProfilerTask taskType) {
    Long count = taskCounts.get(taskType);
    if (count == null) {
      return 0;
    }
    return count;
  }

  /**
   * Iterator over all {@link ProfilerTask}s that were executed at least once and have a total
   * duration greater than 0.
   */
  @Override
  public Iterator<ProfilerTask> iterator() {
    return Iterators.filter(
        taskCounts.keySet().iterator(),
        taskType -> getTotalDurationNanos(taskType) > 0 && wasExecuted(taskType));
  }
}

