// 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.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.InfoItem;
import com.google.devtools.build.lib.runtime.commands.info.BlazeBinInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.BlazeGenfilesInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.BlazeTestlogsInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.BuildLanguageInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.CharacterEncodingInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.ClientEnv;
import com.google.devtools.build.lib.runtime.commands.info.CommittedHeapSizeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.DefaultPackagePathInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.DefaultsPackageInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.ExecutionRootInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.GcCountInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.GcTimeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.InstallBaseInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.JavaHomeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.JavaRuntimeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.JavaVirtualMachineInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.MakeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.MaxHeapSizeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.OutputBaseInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.OutputPathInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.PackagePathInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.ReleaseInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.ServerLogInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.ServerPidInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.StarlarkSemanticsInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.UsedHeapSizeAfterGcInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.UsedHeapSizeInfoItem;
import com.google.devtools.build.lib.runtime.commands.info.WorkspaceInfoItem;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.InterruptedFailureDetails;
import com.google.devtools.build.lib.util.io.OutErr;
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.OptionMetadataTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * Implementation of 'blaze info'.
 */
@Command(name = "info",
         // TODO(bazel-team): this is not really a build command, but needs access to the
         // configuration options to do its job
         builds = true,
         allowResidue = true,
         binaryStdOut = true,
         help = "resource:info.txt",
         shortDescription = "Displays runtime info about the %{product} server.",
         options = { InfoCommand.Options.class },
         completion = "info-key",
         // We have InfoCommand inherit from {@link BuildCommand} because we want all
         // configuration defaults specified in ~/.blazerc for {@code build} to apply to
         // {@code info} too, even though it doesn't actually do a build.
         //
         // (Ideally there would be a way to make {@code info} inherit just the bare
         // minimum of relevant options from {@code build}, i.e. those that affect the
         // values it prints.  But there's no such mechanism.)
         inherits = { BuildCommand.class })
public class InfoCommand implements BlazeCommand {

  /** Options for the info command. */
  public static class Options extends OptionsBase {
    @Option(
      name = "show_make_env",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.LOGGING,
      effectTags = {OptionEffectTag.AFFECTS_OUTPUTS, OptionEffectTag.TERMINAL_OUTPUT},
      help = "Include the \"Make\" environment in the output."
    )
    public boolean showMakeEnvironment;

    @Option(
        name = "experimental_supports_info_crosstool_configuration",
        defaultValue = "true",
        documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
        effectTags = {OptionEffectTag.UNKNOWN},
        metadataTags = {OptionMetadataTag.HIDDEN},
        help = "Noop.")
    public boolean experimentalSupportsInfoCrosstoolConfiguration;
  }

  /**
   * Unchecked variant of {@link AbruptExitException}. Below, we need to throw from the Supplier
   * interface, which does not allow checked exceptions.
   */
  private static class AbruptExitRuntimeException extends RuntimeException {

    private final DetailedExitCode detailedExitCode;

    private AbruptExitRuntimeException(DetailedExitCode exitCode) {
      this.detailedExitCode = exitCode;
    }

    private DetailedExitCode getDetailedExitCode() {
      return detailedExitCode;
    }
  }

  @Override
  public BlazeCommandResult exec(
      final CommandEnvironment env, final OptionsParsingResult optionsParsingResult) {
    final BlazeRuntime runtime = env.getRuntime();
    env.getReporter().switchToAnsiAllowingHandler();
    Options infoOptions = optionsParsingResult.getOptions(Options.class);
    OutErr outErr = env.getReporter().getOutErr();
    // Creating a BuildConfigurationValue is expensive and often unnecessary. Delay the creation
    // until
    // it is needed. We memoize so that it's cached intra-command (it's still created freshly on
    // every command since the configuration can change across commands).
    Supplier<BuildConfigurationValue> configurationSupplier =
        Suppliers.memoize(
            () -> {
              try (SilentCloseable c =
                  Profiler.instance().profile("Creating BuildConfigurationValue")) {
                // In order to be able to answer configuration-specific queries, we need to set up
                // the package path. Since info inherits all the build options, all the necessary
                // information is available here.
                env.syncPackageLoading(optionsParsingResult);
                // TODO(bazel-team): What if there are multiple configurations? [multi-config]
                BuildOptions buildOptions = runtime.createBuildOptions(optionsParsingResult);
                env.getSkyframeExecutor().setBaselineConfiguration(buildOptions);
                return env.getSkyframeExecutor()
                    .getConfiguration(env.getReporter(), buildOptions, /*keepGoing=*/ true);
              } catch (InvalidConfigurationException e) {
                env.getReporter().handle(Event.error(e.getMessage()));
                throw new AbruptExitRuntimeException(e.getDetailedExitCode());
              } catch (AbruptExitException e) {
                throw new AbruptExitRuntimeException(e.getDetailedExitCode());
              } catch (InterruptedException e) {
                env.getReporter().handle(Event.error("interrupted"));
                throw new AbruptExitRuntimeException(
                    InterruptedFailureDetails.detailedExitCode(
                        "command interrupted while syncing package loading"));
              }
            });

    Map<String, InfoItem> items = getInfoItemMap(env, optionsParsingResult);

    try {
      if (infoOptions.showMakeEnvironment) {
        Map<String, String> makeEnv = configurationSupplier.get().getMakeEnvironment();
        for (Map.Entry<String, String> entry : makeEnv.entrySet()) {
          InfoItem item = new MakeInfoItem(entry.getKey(), entry.getValue());
          items.put(item.getName(), item);
        }
      }

      List<String> residue = optionsParsingResult.getResidue();
      env.getEventBus().post(new NoBuildEvent());
      if (!residue.isEmpty()) {
        ImmutableSet.Builder<String> unknownKeysBuilder = ImmutableSet.builder();
        for (String key : residue) {
          byte[] value;
          if (items.containsKey(key)) {
            try (SilentCloseable c = Profiler.instance().profile(key + ".infoItem")) {
              value = items.get(key).get(configurationSupplier, env);
              if (residue.size() > 1) {
                outErr.getOutputStream().write((key + ": ").getBytes(StandardCharsets.UTF_8));
              }
              outErr.getOutputStream().write(value);
            }
          } else {
            unknownKeysBuilder.add(key);
          }
        }
        ImmutableSet<String> unknownKeys = unknownKeysBuilder.build();
        if (!unknownKeys.isEmpty()) {
          String message =
              "unknown key(s): "
                  + unknownKeys.stream()
                      .map(key -> "'" + key + "'")
                      .collect(Collectors.joining(", "));
          env.getReporter().handle(Event.error(message));
          return createFailureResult(
              message,
              ExitCode.COMMAND_LINE_ERROR,
              FailureDetails.InfoCommand.Code.KEY_NOT_RECOGNIZED);
        }
      } else { // print them all
        var unused = configurationSupplier.get(); // We'll need this later anyway
        for (InfoItem infoItem : items.values()) {
          if (infoItem.isHidden()) {
            continue;
          }
          outErr.getOutputStream().write(
              (infoItem.getName() + ": ").getBytes(StandardCharsets.UTF_8));
          try (SilentCloseable c = Profiler.instance().profile(infoItem.getName() + ".infoItem")) {
            outErr.getOutputStream().write(infoItem.get(configurationSupplier, env));
          }
        }
      }
      outErr.getOutputStream().flush();
    } catch (AbruptExitException e) {
      return BlazeCommandResult.detailedExitCode(e.getDetailedExitCode());
    } catch (AbruptExitRuntimeException e) {
      return BlazeCommandResult.detailedExitCode(e.getDetailedExitCode());
    } catch (IOException e) {
      return createFailureResult(
          "Cannot write info block: " + e.getMessage(),
          ExitCode.LOCAL_ENVIRONMENTAL_ERROR,
          FailureDetails.InfoCommand.Code.ALL_INFO_WRITE_FAILURE);
    } catch (InterruptedException e) {
      return BlazeCommandResult.detailedExitCode(
          InterruptedFailureDetails.detailedExitCode("info interrupted"));
    }
    return BlazeCommandResult.success();
  }

  private static BlazeCommandResult createFailureResult(
      String message, ExitCode exitCode, FailureDetails.InfoCommand.Code detailedCode) {
    return BlazeCommandResult.detailedExitCode(
        DetailedExitCode.of(
            exitCode,
            FailureDetail.newBuilder()
                .setMessage(message)
                .setInfoCommand(FailureDetails.InfoCommand.newBuilder().setCode(detailedCode))
                .build()));
  }

  private static Map<String, InfoItem> getHardwiredInfoItemMap(
      OptionsParsingResult commandOptions, String productName) {
    List<InfoItem> hardwiredInfoItems =
        ImmutableList.<InfoItem>of(
            new WorkspaceInfoItem(),
            new InstallBaseInfoItem(),
            new OutputBaseInfoItem(productName),
            new ExecutionRootInfoItem(),
            new OutputPathInfoItem(),
            new ClientEnv(),
            new BlazeBinInfoItem(productName),
            new BlazeGenfilesInfoItem(productName),
            new BlazeTestlogsInfoItem(productName),
            new ReleaseInfoItem(productName),
            new ServerPidInfoItem(productName),
            new ServerLogInfoItem(productName),
            new PackagePathInfoItem(commandOptions),
            new UsedHeapSizeInfoItem(),
            new UsedHeapSizeAfterGcInfoItem(),
            new CommittedHeapSizeInfoItem(),
            new MaxHeapSizeInfoItem(),
            new GcTimeInfoItem(),
            new GcCountInfoItem(),
            new JavaRuntimeInfoItem(),
            new JavaVirtualMachineInfoItem(),
            new JavaHomeInfoItem(),
            new CharacterEncodingInfoItem(),
            new DefaultsPackageInfoItem(),
            new BuildLanguageInfoItem(),
            new DefaultPackagePathInfoItem(commandOptions),
            new StarlarkSemanticsInfoItem(commandOptions));
    ImmutableMap.Builder<String, InfoItem> result = new ImmutableMap.Builder<>();
    for (InfoItem item : hardwiredInfoItems) {
      result.put(item.getName(), item);
    }
    return result.buildOrThrow();
  }

  public static List<String> getHardwiredInfoItemNames(String productName) {
    ImmutableList.Builder<String> result = new ImmutableList.Builder<>();
    for (String name : InfoCommand.getHardwiredInfoItemMap(null, productName).keySet()) {
      result.add(name);
    }
    return result.build();
  }

  static Map<String, InfoItem> getInfoItemMap(
      CommandEnvironment env, OptionsParsingResult optionsParsingResult) {
    Map<String, InfoItem> items = new TreeMap<>(env.getRuntime().getInfoItems());
    items.putAll(getHardwiredInfoItemMap(optionsParsingResult, env.getRuntime().getProductName()));
    return items;
  }
}
