// Copyright 2018 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.grapher;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.profiler.TimeSeries;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.zip.GZIPInputStream;
import javax.annotation.Nullable;

/**
 * An experimental tool to turn Json profiles into graphs. Do not depend on the continuing existence
 * of this tool.
 *
 * <p>Run this tool like so: bazel run \
 * //src/main/java/com/google/devtools/build/lib/profiler:profiler-grapher \
 * -- /path/to/command.profile > /tmp/tmp.csv
 *
 * <p>Plot the resulting CSV with gnuplot like so: gnuplot -p -e \
 * "set datafile sep ','; plot for [col=1:3] '/tmp/tmp.csv' using col lw 2 with lines \
 * title columnheader"
 */
public class ProfileGrapher {
  public static final long DEFAULT_BUCKET_SIZE_MILLIS = 1000;

  // Decode a JSON object and flattens any nested JSON objects.
  private static Map<String, Object> decodeJsonObject(JsonReader reader) throws IOException {
    reader.beginObject();
    Map<String, Object> data = new HashMap<>();
    while (reader.hasNext()) {
      String name = reader.nextName();
      Object value;
      switch (reader.peek()) {
        case BOOLEAN:
          value = reader.nextBoolean();
          break;
        case NUMBER:
          value = reader.nextDouble();
          break;
        case STRING:
          value = reader.nextString();
          break;
        case BEGIN_OBJECT:
          value = null;
          Map<String, Object> childData = decodeJsonObject(reader);
          for (Map.Entry<String, Object> entry : childData.entrySet()) {
            data.put(name + "." + entry.getKey(), entry.getValue());
          }
          break;
        default:
          reader.skipValue();
          continue;
      }
      data.put(name, value);
    }
    reader.endObject();
    return data;
  }

  public static void main(String[] args) throws IOException {
    if (args.length != 1) {
      System.err.println("Requires filename of a Bazel profile in Chrome event trace format.");
      System.exit(1);
    }
    String filename = args[0];
    boolean gzipped = filename.endsWith(".gz");

    // TODO(twerth): Make it possible to select the set of profiler task descriptions on the command
    // line.
    ImmutableList<String> profilerTaskDescriptions =
        ImmutableList.of(
            "Remote execution process wall time",
            "action processing",
            "Remote execution file fetching");
    Map<String, TimeSeries> seriesMap = new LinkedHashMap<>();
    for (String profilerTaskDescription : profilerTaskDescriptions) {
      seriesMap.put(profilerTaskDescription, new TimeSeries(0, DEFAULT_BUCKET_SIZE_MILLIS));
    }

    long maxEndTime = 0;
    try (JsonReader reader =
        new JsonReader(
            new BufferedReader(
                new InputStreamReader(
                    maybeUnzip(new FileInputStream(filename), gzipped), StandardCharsets.UTF_8)))) {
      if (reader.peek() == JsonToken.BEGIN_OBJECT) {
        reader.beginObject();
        while (reader.hasNext()) {
          if ("traceEvents".equals(reader.nextName())) {
            break;
          }
          reader.skipValue();
        }
      }
      reader.beginArray();
      while (reader.hasNext()) {
        Map<String, Object> data = decodeJsonObject(reader);
        Object name = data.get("name");
        if ("cpu counters".equals(name)) {
          seriesMap.putIfAbsent("cpu counters", new TimeSeries(0, DEFAULT_BUCKET_SIZE_MILLIS));
          TimeSeries series = seriesMap.get(name);
          Double ts = (Double) data.get("ts");
          long startTimeMillis = Math.round(ts.doubleValue() / 1000);
          Double cpuValue = Double.valueOf((String) data.get("args.cpu"));
          series.addRange(startTimeMillis, startTimeMillis + DEFAULT_BUCKET_SIZE_MILLIS, cpuValue);
        } else {
          Object cat = data.get("cat");
          TimeSeries series = seriesMap.get(cat);
          if (series != null) {
            Long endTimeMillis = decodeAndAdd(series, data);
            if (endTimeMillis != null) {
              maxEndTime = Math.max(maxEndTime, endTimeMillis);
            }
          }
        }
      }
      reader.endArray();
    }

    // Instead of generating a CSV here, we could generate Json and use the Google Charts API to
    // generate interactive web graphs (https://developers.google.com/chart/).
    int len = (int) (maxEndTime / DEFAULT_BUCKET_SIZE_MILLIS) + 1;
    double[][] numbers = new double[seriesMap.size()][];
    List<Map.Entry<String, TimeSeries>> allSeries = new ArrayList<>(seriesMap.entrySet());
    // Write the titles in the first line of the CSV
    StringJoiner stringJoiner = new StringJoiner(",");
    for (int i = 0; i < numbers.length; i++) {
      stringJoiner.add(allSeries.get(i).getKey());
      numbers[i] = allSeries.get(i).getValue().toDoubleArray(len);
    }
    System.out.println(stringJoiner.toString());

    for (int i = 0; i < numbers[0].length; i++) {
      stringJoiner = new StringJoiner(",");
      for (int j = 0; j < numbers.length; j++) {
        stringJoiner.add(String.valueOf(numbers[j][i]));
      }
      System.out.println(stringJoiner.toString());
    }
  }

  private static InputStream maybeUnzip(InputStream in, boolean gzipped) throws IOException {
    if (!gzipped) {
      return in;
    }
    return new GZIPInputStream(in);
  }

  /**
   * Decodes the start time and duration from the data, adds it to the given series and returns the
   * end time in milliseconds if it was possible to decode the data, otherwise null.
   */
  @Nullable
  private static Long decodeAndAdd(TimeSeries series, Map<String, Object> data) {
    Double ts = (Double) data.get("ts");
    Double dur = (Double) data.get("dur");
    if (ts == null || dur == null) {
      return null;
    }
    long durationMillis = Math.round(dur.doubleValue() / 1000);
    long startTimeMillis = Math.round(ts.doubleValue() / 1000);
    long endTimeMillis = startTimeMillis + durationMillis;
    series.addRange(startTimeMillis, endTimeMillis);
    return endTimeMillis;
  }
}
