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

import com.google.common.base.Optional;
import com.google.devtools.build.lib.profiler.ProfilePhase;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo;
import com.google.devtools.build.lib.profiler.chart.AggregatingChartCreator;
import com.google.devtools.build.lib.profiler.chart.Chart;
import com.google.devtools.build.lib.profiler.chart.ChartCreator;
import com.google.devtools.build.lib.profiler.chart.DetailedChartCreator;
import com.google.devtools.build.lib.profiler.chart.HtmlChartVisitor;
import com.google.devtools.build.lib.profiler.statistics.CriticalPathStatistics;
import com.google.devtools.build.lib.profiler.statistics.MultiProfileStatistics;
import com.google.devtools.build.lib.profiler.statistics.PhaseStatistics;
import com.google.devtools.build.lib.profiler.statistics.PhaseSummaryStatistics;
import com.google.devtools.build.lib.profiler.statistics.SkylarkStatistics;
import com.google.devtools.build.lib.vfs.Path;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.EnumMap;

/**
 * Creates an HTML page displaying the various statistics and charts generated
 * from the profile file.
 */
public final class HtmlCreator extends HtmlPrinter {

  private final Optional<Chart> chart;
  private final HtmlChartVisitor chartVisitor;
  private final Optional<SkylarkHtml> skylarkStats;
  private final Optional<MultiProfilePhaseHtml> multiFileStats;
  private final String title;
  private final PhaseHtml phases;

  private HtmlCreator(
      PrintStream out,
      String title,
      Optional<Chart> chart,
      Optional<SkylarkHtml> skylarkStats,
      Optional<MultiProfilePhaseHtml> multiFileStats,
      PhaseHtml phases,
      int htmlPixelsPerSecond) {
    super(out);
    this.title = title;
    this.chart = chart;
    this.skylarkStats = skylarkStats;
    this.phases = phases;
    this.multiFileStats = multiFileStats;
    chartVisitor = new HtmlChartVisitor(out, htmlPixelsPerSecond);
  }

  /**
   * Output the HTML depending on which statistics should be printed.
   */
  private void print() {
    htmlFrontMatter();
    if (chart.isPresent()) {
      chart.get().accept(chartVisitor);
    }

    element("a", "name", "Statistics");
    element("h2", "Statistics");
    phases.print();

    if (multiFileStats.isPresent()) {
      multiFileStats.get().printHtmlBody();
    }
    if (skylarkStats.isPresent()) {
      skylarkStats.get().printHtmlBody();
    }
    htmlBackMatter();
  }

  /**
   * Print opening tags, CSS and JavaScript
   */
  private void htmlFrontMatter() {
    lnOpen("html");
    lnOpen("head");
    lnElement("title", title);

    printVisualizationJs();

    if (chart.isPresent()) {
      chartVisitor.printCss(chart.get().getSortedTypes());
    }

    phases.printCss();

    if (multiFileStats.isPresent()) {
      multiFileStats.get().printHtmlHead();
    }
    if (skylarkStats.isPresent()) {
      skylarkStats.get().printHtmlHead();
    }

    lnClose();
    lnOpen("body");
    lnElement("h1", title);
  }

  private void htmlBackMatter() {
    lnClose();
    lnClose();
  }

  /**
   * Print code for loading the Google Visualization JS library.
   *
   * <p>Used for the charts and tables for {@link SkylarkHtml} and {@link MultiProfilePhaseHtml}.
   * Also adds a callback on load of the library which draws the charts and tables.
   */
  private void printVisualizationJs() {
    lnElement("script", "type", "text/javascript", "src", "https://www.google.com/jsapi");
    lnOpen("script", "type", "text/javascript");
    lnPrint("google.load(\"visualization\", \"1.1\", {packages:[\"corechart\",\"table\"]});");
    lnPrint("google.setOnLoadCallback(drawVisualization);");
    lnPrint("function drawVisualization() {");
    down();
    if (skylarkStats.isPresent()) {
      skylarkStats.get().printVisualizationCallbackJs();
    }
    if (multiFileStats.isPresent()) {
      multiFileStats.get().printVisualizationCallbackJs();
    }
    up();
    lnPrint("}");
    lnClose(); // script
  }

  /**
   * Writes the HTML profiling information.
   *
   * @throws IOException
   */
  public static void create(
      ProfileInfo info,
      Path htmlFile,
      PhaseSummaryStatistics phaseSummaryStats,
      EnumMap<ProfilePhase, PhaseStatistics> statistics,
      CriticalPathStatistics criticalPathStats,
      boolean detailed,
      int htmlPixelsPerSecond,
      int vfsStatsLimit,
      boolean generateChart,
      boolean generateHistograms)
      throws IOException {
    try (PrintStream out = new PrintStream(new BufferedOutputStream(htmlFile.getOutputStream()))) {
      PhaseHtml phaseHtml =
          new PhaseHtml(
              out,
              phaseSummaryStats,
              statistics,
              Optional.of(criticalPathStats),
              vfsStatsLimit);
      Optional<SkylarkHtml> skylarkStats = Optional.absent();
      Optional<Chart> chart = Optional.absent();
      if (detailed) {
        skylarkStats =
            Optional.of(new SkylarkHtml(out, new SkylarkStatistics(info), generateHistograms));
      }
      if (generateChart) {
        ChartCreator chartCreator;
        if (detailed) {
          chartCreator = new DetailedChartCreator(info);
        } else {
          chartCreator = new AggregatingChartCreator(info);
        }
        // Bar widths are in nanoseconds. Therefore, because of integer division, the following
        // expression is the minimum nanosecond width that would correspond to a non-zero
        // number of pixels.
        long minBarWidth = 1000000000L / htmlPixelsPerSecond;
        chart = Optional.of(chartCreator.create(minBarWidth));
      }
      new HtmlCreator(
              out,
              info.comment,
              chart,
              skylarkStats,
              Optional.<MultiProfilePhaseHtml>absent(),
              phaseHtml,
              htmlPixelsPerSecond)
          .print();
    }
  }

  /**
   * Writes the HTML profiling information for multiple files.
   *
   * <p>Does not print a {@link Chart} or even multiple charts and no Skylark histograms.
   */
  public static void create(
      PrintStream out,
      MultiProfileStatistics statistics,
      boolean detailed,
      int htmlPixelsPerSecond,
      int vfsStatsLimit) {
    PhaseHtml phaseHtml =
        new PhaseHtml(
            out,
            statistics.getSummaryStatistics(),
            statistics.getSummaryPhaseStatistics(),
            vfsStatsLimit);
    Optional<SkylarkHtml> skylarkStats;
    if (detailed) {
      skylarkStats = Optional.of(new SkylarkHtml(out, statistics.getSkylarkStatistics(), false));
    } else {
      skylarkStats = Optional.absent();
    }
    new HtmlCreator(
            out,
            "Statistics from multiple profile files",
            Optional.<Chart>absent(),
            skylarkStats,
            Optional.of(new MultiProfilePhaseHtml(out, statistics)),
            phaseHtml,
            htmlPixelsPerSecond)
        .print();
  }
}
