// 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.ProfileInfo;
import com.google.devtools.build.lib.profiler.ProfilePhase;
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,
      int missingActionsCount,
      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),
              Optional.of(missingActionsCount),
              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);
        }
        chart = Optional.of(chartCreator.create());
      }
      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();
  }
}
