// Copyright 2014 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.runtime.commands;

import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.profiler.JsonProfile;
import com.google.devtools.build.lib.profiler.output.PhaseText;
import com.google.devtools.build.lib.profiler.statistics.CriticalPathStatistics;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.ProfileCommand.Code;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;

/** Command line wrapper for analyzing Blaze build profiles. */
@Command(
  name = "analyze-profile",
  options = {ProfileCommand.ProfileOptions.class},
  shortDescription = "Analyzes build profile data.",
  help = "resource:analyze-profile.txt",
  allowResidue = true,
  completion = "path",
  mustRunInWorkspace = false
)
public final class ProfileCommand implements BlazeCommand {

  public static class DumpConverter extends Converters.StringSetConverter {
    public DumpConverter() {
      super("text", "raw");
    }
  }

  public static class ProfileOptions extends OptionsBase {
    @Option(
        name = "dump",
        abbrev = 'd',
        converter = DumpConverter.class,
        defaultValue = "null",
        documentationCategory = OptionDocumentationCategory.LOGGING,
        effectTags = {OptionEffectTag.BAZEL_MONITORING},
        help =
            "output full profile data dump either in human-readable 'text' format or"
                + " script-friendly 'raw' format.")
    public String dumpMode;
  }

  /**
   * Note that this is just a basic check whether the file is zlib compressed.
   *
   * <p>Other checks (e.g. the magic bytes of the binary profile file) are done later.
   */
  private static boolean isOldBinaryProfile(File profile) {
    try (InputStream inputStream = new FileInputStream(profile)) {
      byte[] magicBytes = new byte[2];
      int numBytesRead = inputStream.read(magicBytes);
      if (numBytesRead == 2
          && magicBytes[0] == (byte) 0x78
          && (magicBytes[1] == (byte) 0x01
              || magicBytes[1] == (byte) 0x9C
              || magicBytes[1] == (byte) 0xDA)) {
        return true;
      }
    } catch (Exception e) {
      // silently ignore any exception
    }
    return false;
  }

  @Override
  public BlazeCommandResult exec(final CommandEnvironment env, OptionsParsingResult options) {
    ProfileOptions profileOptions = options.getOptions(ProfileOptions.class);
    String dumpMode = profileOptions.dumpMode;

    try (PrintStream out = getOutputStream(env)) {
      Reporter reporter = env.getReporter();

      reporter.handle(
          Event.warn(
              "This information is intended for consumption by Bazel developers"
                  + " only, and may change at any time. Script against it at your own risk"));
      for (String name : options.getResidue()) {
        Path profileFile = env.getWorkingDirectory().getRelative(name);
        if (isOldBinaryProfile(profileFile.getPathFile())) {
          String message =
              "The old binary profile format is deprecated."
                  + " Use the JSON trace profile instead.";
          reporter.handle(Event.error(message));
          return createFailureResult(message, Code.OLD_BINARY_FORMAT_UNSUPPORTED);
        } else {
          try {
            if (dumpMode != null) {
              reporter.handle(
                  Event.warn(
                      "--dump has not been implemented yet for the JSON profile, ignoring."));
            }
            JsonProfile jsonProfile = new JsonProfile(profileFile.getPathFile());

            JsonProfile.BuildMetadata buildMetadata = jsonProfile.getBuildMetadata();
            if (buildMetadata != null) {
              reporter.handle(
                  Event.info(
                      "Profile created on "
                          + buildMetadata.date()
                          + ", build ID: "
                          + buildMetadata.buildId()
                          + ", output base: "
                          + buildMetadata.outputBase()));
            }

            new PhaseText(
                    out,
                    jsonProfile.getPhaseSummaryStatistics(),
                    new CriticalPathStatistics(jsonProfile.getTraceEvents()))
                .print();
          } catch (IOException e) {
            String message = "Failed to analyze profile file(s): " + e.getMessage();
            reporter.handle(Event.error(message));
            return createFailureResult(message, Code.FILE_READ_FAILURE);
          }
        }
      }
    }
    return BlazeCommandResult.success();
  }

  private static PrintStream getOutputStream(CommandEnvironment env) {
    return new PrintStream(
        new BufferedOutputStream(env.getReporter().getOutErr().getOutputStream()), false);
  }

  private static BlazeCommandResult createFailureResult(String message, Code detailedCode) {
    return BlazeCommandResult.failureDetail(
        FailureDetail.newBuilder()
            .setMessage(message)
            .setProfileCommand(FailureDetails.ProfileCommand.newBuilder().setCode(detailedCode))
            .build());
  }
}
