// 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 static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ProtoUtils;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.AllowedRuleClassInfo;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.AttributeDefinition;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.BuildLanguage;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.RuleDefinition;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.LogHandlerQuerier;
import com.google.devtools.build.lib.util.ProcessUtils;
import com.google.devtools.build.lib.util.StringUtilities;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * An item that is returned by <code>blaze info</code>.
 */
public abstract class InfoItem {
  protected final String name;
  protected final String description;
  protected final boolean hidden;

  protected InfoItem(String name,
      String description,
      boolean hidden) {
    this.name = name;
    this.description = description;
    this.hidden = hidden;
  }

  protected InfoItem(String name,
      String description) {
    this(name, description, false);
  }

  /**
   * The name of the info key.
   */
  public String getName() {
    return name;
  }

  /**
   * The help description of the info key.
   */
  public String getDescription() {
    return description;
  }

  /**
   * Whether the key is printed when "blaze info" is invoked without arguments.
   *
   * <p>This is usually true for info keys that take multiple lines, thus, cannot really be
   * included in the output of argumentless "blaze info".
   */
  public boolean isHidden() {
    return hidden;
  }

  /**
   * Returns the value of the info key. The return value is directly printed to stdout.
   */
  public abstract byte[] get(
      Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
      throws AbruptExitException, InterruptedException;

  protected static byte[] print(Object value) {
    if (value instanceof byte[]) {
      return (byte[]) value;
    }
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(
        outputStream, StandardCharsets.UTF_8));
    writer.print(value + "\n");
    writer.flush();
    return outputStream.toByteArray();
  }

  /**
   * Info item for the workspace directory.
   */
  public static final class WorkspaceInfoItem extends InfoItem {
    public WorkspaceInfoItem() {
      super("workspace",
          "The working directory of the server.");
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getRuntime().getWorkspace().getWorkspace());
    }
  }

  /**
   * Info item for the install_base directory.
   */
  public static final class InstallBaseInfoItem extends InfoItem {
    public InstallBaseInfoItem() {
      super("install_base",
          "The installation base directory.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getRuntime().getWorkspace().getInstallBase());
    }
  }

  /**
   * Info item for the output_base directory.
   */
  public static final class OutputBaseInfoItem extends InfoItem {
    public OutputBaseInfoItem(String productName) {
      super("output_base",
          "A directory for shared " + productName
          + " state as well as tool and strategy specific subdirectories.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getRuntime().getWorkspace().getOutputBase());
    }
  }

  /**
   * Info item for the execution_root directory.
   */
  public static final class ExecutionRootInfoItem extends InfoItem {
    public ExecutionRootInfoItem() {
      super("execution_root",
          "A directory that makes all input and output files visible to the build.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(env.getDirectories().getExecRoot(
          configurationSupplier.get().getMainRepositoryName()));
    }
  }

  /**
   * Info item for the output_path directory.
   */
  public static final class OutputPathInfoItem extends InfoItem {
    public OutputPathInfoItem() {
      super("output_path",
          "Output directory",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(
          env.getDirectories().getOutputPath(configurationSupplier.get().getMainRepositoryName()));
    }
  }

  /**
   * Info item for the {blaze,bazel}-bin directory.
   */
  public static final class BlazeBinInfoItem extends InfoItem {
    public BlazeBinInfoItem(String productName) {
      super(productName + "-bin",
          "Configuration dependent directory for binaries.",
          false);
    }

    // This is one of the three (non-hidden) info items that require a configuration, because the
    // corresponding paths contain the short name. Maybe we should recommend using the symlinks
    // or make them hidden by default?
    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(configurationSupplier);
      return print(configurationSupplier.get().getBinDirectory(RepositoryName.MAIN).getRoot());
    }
  }

  /**
   * Info item for the {blaze,bazel}-genfiles directory.
   */
  public static final class BlazeGenfilesInfoItem extends InfoItem {
    public BlazeGenfilesInfoItem(String productName) {
      super(productName + "-genfiles",
          "Configuration dependent directory for generated files.",
          false);
    }

    // This is one of the three (non-hidden) info items that require a configuration, because the
    // corresponding paths contain the short name. Maybe we should recommend using the symlinks
    // or make them hidden by default?
    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(configurationSupplier);
      return print(configurationSupplier.get().getGenfilesDirectory(RepositoryName.MAIN).getRoot());
    }
  }

  /**
   * Info item for the {blaze,bazel}-testlogs directory.
   */
  public static final class BlazeTestlogsInfoItem extends InfoItem {
    public BlazeTestlogsInfoItem(String productName) {
      super(productName + "-testlogs",
          "Configuration dependent directory for logs from a test run.",
          false);
    }

    // This is one of the three (non-hidden) info items that require a configuration, because the
    // corresponding paths contain the short name. Maybe we should recommend using the symlinks
    // or make them hidden by default?
    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(configurationSupplier);
      return print(configurationSupplier.get().getTestLogsDirectory(RepositoryName.MAIN).getRoot());
    }
  }

  /** Info item for server_log path. */
  public static class ServerLogInfoItem extends InfoItem {
    private static final Logger logger = Logger.getLogger(ServerLogInfoItem.class.getName());

    /**
     * Constructs an info item for the server log path.
     *
     * @param productName name of the tool whose server log path will be queried
     */
    public ServerLogInfoItem(String productName) {
      super("server_log", productName + " server log path", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      LogHandlerQuerier logHandlerQuerier;
      try {
        logHandlerQuerier = LogHandlerQuerier.getConfiguredInstance();
      } catch (IllegalStateException e) {
        // Non-fatal error: we don't want the "info" command to crash.
        logger.log(Level.WARNING, "Could not find a querier for server log location", e);
        return print("UNKNOWN LOG LOCATION");
      }
      Optional<java.nio.file.Path> loggerFilePath;
      try {
        loggerFilePath = logHandlerQuerier.getLoggerFilePath(logger);
      } catch (IllegalArgumentException e) {
        // Non-fatal error: we don't want the "info" command to crash.
        logger.log(Level.WARNING, "Could not query for server log location", e);
        return print("UNKNOWN LOG LOCATION");
      }
      // If loggerFilePath is empty, then no log file is currently open, so an empty string is the
      // correct output.
      return print(loggerFilePath.map(java.nio.file.Path::toString).orElse(""));
    }
  }

  /**
   * Info item for release
   */
  public static final class ReleaseInfoItem extends InfoItem {
    public ReleaseInfoItem(String productName) {
      super("release",
          productName + " release identifier",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(BlazeVersionInfo.instance().getReleaseName());
    }
  }

  /**
   * Info item for server_pid
   */
  public static final class ServerPidInfoItem extends InfoItem {
    public ServerPidInfoItem(String productName) {
      super("server_pid",
          productName + " process id",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(ProcessUtils.getpid());
    }
  }

  /**
   * Info item for package_path
   */
  public static final class PackagePathInfoItem extends InfoItem {
    private final OptionsParsingResult commandOptions;

    public PackagePathInfoItem(OptionsParsingResult commandOptions) {
      super("package_path",
          "The search path for resolving package labels.",
          false);
      this.commandOptions = commandOptions;
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(commandOptions);
      PackageCacheOptions packageCacheOptions =
          commandOptions.getOptions(PackageCacheOptions.class);
      return print(Joiner.on(":").join(packageCacheOptions.packagePath));
    }
  }

  private static MemoryUsage getMemoryUsage() {
    MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
    return memBean.getHeapMemoryUsage();
  }

  /**
   * Info item for the used heap size
   */
  public static final class UsedHeapSizeInfoItem extends InfoItem {
    public UsedHeapSizeInfoItem() {
      super("used-heap-size",
          "The amount of used memory in bytes. Note that this is not a "
          + "good indicator of the actual memory use, as it includes any remaining inaccessible "
          + "memory.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed()));
    }
  }

  /**
   * Info item for the used heap size after garbage collection
   */
  public static final class UsedHeapSizeAfterGcInfoItem extends InfoItem {
    public UsedHeapSizeAfterGcInfoItem() {
      super("used-heap-size-after-gc",
          "The amount of used memory in bytes after a call to System.gc().",
          true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      System.gc();
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed()));
    }
  }

  /**
   * Info item for the committed heap size
   */
  public static final class CommitedHeapSizeInfoItem extends InfoItem {
    public CommitedHeapSizeInfoItem() {
      super("committed-heap-size",
          "The amount of memory in bytes that is committed for the Java virtual machine to use",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getCommitted()));
    }
  }

  /**
   * Info item for the max heap size
   */
  public static final class MaxHeapSizeInfoItem extends InfoItem {
    public MaxHeapSizeInfoItem() {
      super("max-heap-size",
          "The maximum amount of memory in bytes that can be used for memory management.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getMax()));
    }
  }

  /**
   * Info item for the gc-count
   */
  public static final class GcCountInfoItem extends InfoItem {
    public GcCountInfoItem() {
      super("gc-count",
          "Number of garbage collection runs.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      // The documentation is not very clear on what it means to have more than
      // one GC MXBean, so we just sum them up.
      long gcCount = 0;
      for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
        gcCount += gcBean.getCollectionCount();
      }
      return print(gcCount + "");
    }
  }

  /** Info item for the name and version of the Java runtime environment. */
  public static final class JavaRuntimeInfoItem extends InfoItem {
    public JavaRuntimeInfoItem() {
      super("java-runtime", "Name and version of the current Java runtime environment.", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(
          String.format(
              "%s (build %s) by %s",
              System.getProperty("java.runtime.name", "Unknown runtime"),
              System.getProperty("java.runtime.version", "unknown"),
              System.getProperty("java.vendor", "unknown")));
    }
  }

  /** Info item for the name and version of the Java VM. */
  public static final class JavaVirtualMachineInfoItem extends InfoItem {
    public JavaVirtualMachineInfoItem() {
      super("java-vm", "Name and version of the current Java virtual machine.", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(
          String.format(
              "%s (build %s, %s) by %s",
              System.getProperty("java.vm.name", "Unknown VM"),
              System.getProperty("java.vm.version", "unknown"),
              System.getProperty("java.vm.info", "unknown"),
              System.getProperty("java.vm.vendor", "unknown")));
    }
  }

  /** Info item for the location of the Java runtime. */
  public static final class JavaHomeInfoItem extends InfoItem {
    public JavaHomeInfoItem() {
      super("java-home", "Location of the current Java runtime.", false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      String javaHome = System.getProperty("java.home");
      if (javaHome == null) {
        return print("unknown");
      }
      // Tunnel through a Path object in order to normalize the representation of the path.
      Path javaHomePath = env.getRuntime().getFileSystem().getPath(javaHome);
      return print(javaHomePath.getPathString());
    }
  }

  /** Info item for the current character encoding settings. */
  public static final class CharacterEncodingInfoItem extends InfoItem {
    public CharacterEncodingInfoItem() {
      super(
          "character-encoding",
          "Information about the character encoding used by the running JVM.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      return print(
          String.format(
              "file.encoding = %s, defaultCharset = %s",
              System.getProperty("file.encoding", "unknown"), Charset.defaultCharset().name()));
    }
  }

  /** Info item for the gc-time */
  public static final class GcTimeInfoItem extends InfoItem {
    public GcTimeInfoItem() {
      super("gc-time",
          "The approximate accumulated time spend on garbage collection.",
          false);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      // The documentation is not very clear on what it means to have more than
      // one GC MXBean, so we just sum them up.
      long gcTime = 0;
      for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
        gcTime += gcBean.getCollectionTime();
      }
      return print(gcTime + "ms");
    }
  }

  /** Info item for the effective current client environment. */
  public static final class ClientEnv extends InfoItem {
    public ClientEnv() {
      super(
          "client-env",
          "The specifications that need to be added to the project-specific rc file to freeze the"
              + " current client environment",
          true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      String result = "";
      for (Map.Entry<String, String> entry : env.getWhitelistedActionEnv().entrySet()) {
        // TODO(bazel-team): as the syntax of our rc-files does not support to express new-lines in
        // values, we produce syntax errors if the value of the entry contains a newline character.
        result += "build --action_env=" + entry.getKey() + "=" + entry.getValue() + "\n";
      }
      for (Map.Entry<String, String> entry : env.getWhitelistedTestEnv().entrySet()) {
        // TODO(bazel-team): as the syntax of our rc-files does not support to express new-lines in
        // values, we produce syntax errors if the value of the entry contains a newline character.
        result += "build --test_env=" + entry.getKey() + "=" + entry.getValue() + "\n";
      }
      return print(result);
    }
  }

  /**
   * Info item for the default package. It is deprecated, it still works, when explicitly requested,
   * but are not shown by default. It prints multi-line messages and thus don't play well with grep.
   * We don't print them unless explicitly requested.
   *
   * @deprecated
   */
  // TODO(lberki): Try to remove this using an incompatible flag.
  @Deprecated
  public static final class DefaultsPackageInfoItem extends InfoItem {
    public DefaultsPackageInfoItem() {
      super("defaults-package", "Obsolete. Retained for backwards compatibility.", true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) {
      checkNotNull(env);
      return print("");
    }
  }

  private static AllowedRuleClassInfo getAllowedRuleClasses(
      Collection<RuleClass> ruleClasses, Attribute attr) {
    AllowedRuleClassInfo.Builder info = AllowedRuleClassInfo.newBuilder();
    info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.ANY);

    if (attr.isStrictLabelCheckingEnabled()
        && attr.getAllowedRuleClassesPredicate() != Predicates.<RuleClass>alwaysTrue()) {
      info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.SPECIFIED);
      Predicate<RuleClass> filter = attr.getAllowedRuleClassesPredicate();
      for (RuleClass otherClass : Iterables.filter(ruleClasses, filter)) {
        if (!isAbstractRule(otherClass)) {
          info.addAllowedRuleClass(otherClass.getName());
        }
      }
    }

    return info.build();
  }

  private static boolean isAbstractRule(RuleClass c) {
    return c.getName().startsWith("$");
  }

  /**
   * Returns a byte array containing a proto-buffer describing the build language.
   */
  private static byte[] getBuildLanguageDefinition(RuleClassProvider provider) {
    BuildLanguage.Builder resultPb = BuildLanguage.newBuilder();
    Collection<RuleClass> ruleClasses = provider.getRuleClassMap().values();
    for (RuleClass ruleClass : ruleClasses) {
      if (isAbstractRule(ruleClass)) {
        continue;
      }

      RuleDefinition.Builder rulePb = RuleDefinition.newBuilder();
      rulePb.setName(ruleClass.getName());
      for (Attribute attr : ruleClass.getAttributes()) {
        AttributeDefinition.Builder attrPb = AttributeDefinition.newBuilder();
        attrPb.setName(attr.getName());
        // The protocol compiler, in its infinite wisdom, generates the field as one of the
        // integer type and the getTypeEnum() method is missing. WTF?
        attrPb.setType(ProtoUtils.getDiscriminatorFromType(attr.getType()));
        attrPb.setMandatory(attr.isMandatory());

        if (BuildType.isLabelType(attr.getType())) {
          attrPb.setAllowedRuleClasses(getAllowedRuleClasses(ruleClasses, attr));
        }

        rulePb.addAttribute(attrPb);
      }

      resultPb.addRule(rulePb);
    }

    return resultPb.build().toByteArray();
  }

  /**
   * Info item for the build language. It is deprecated, it still works, when
   * explicitly requested, but are not shown by default. It prints multi-line messages and thus
   * don't play well with grep. We don't print them unless explicitly requested.
   * @Deprecated
   */
  @Deprecated
  public static final class BuildLanguageInfoItem extends InfoItem {
    public BuildLanguageInfoItem() {
      super("build-language",
          "A protobuffer with the build language structure",
          true);
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(env);
      return print(getBuildLanguageDefinition(env.getRuntime().getRuleClassProvider()));
    }
  }

  /**
   * Info item for the default package path. It is deprecated, it still works, when
   * explicitly requested, but are not shown by default. It prints multi-line messages and thus
   * don't play well with grep. We don't print them unless explicitly requested.
   * @deprecated
   */
  @Deprecated
  public static final class DefaultPackagePathInfoItem extends InfoItem {
    private final OptionsParsingResult commandOptions;

    public DefaultPackagePathInfoItem(OptionsParsingResult commandOptions) {
      super("default-package-path",
          "The default package path",
          true);
      this.commandOptions = commandOptions;
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
        throws AbruptExitException {
      checkNotNull(commandOptions);
      return print(Joiner.on(":").join(
          commandOptions.getOptions(PackageCacheOptions.class).packagePath));
    }
  }

  /**
   * Info item for the make environment.
   */
  public static class MakeInfoItem extends InfoItem {
    public MakeInfoItem(String name, String description) {
      super(name, description, false);
    }
    @Override
    public String getDescription() {
      return "Make environment variable '" + name + "'";
    }

    @Override
    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) {
      return print(description);
    }
  }
}
