// Copyright 2017 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;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.io.BaseEncoding;
import com.google.devtools.build.lib.buildeventstream.BuildEventContext;
import com.google.devtools.build.lib.buildeventstream.BuildEventId;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventWithOrderConstraint;
import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent;
import com.google.devtools.build.lib.runtime.proto.CommandLineOuterClass.ChunkList;
import com.google.devtools.build.lib.runtime.proto.CommandLineOuterClass.CommandLine;
import com.google.devtools.build.lib.runtime.proto.CommandLineOuterClass.CommandLineSection;
import com.google.devtools.build.lib.runtime.proto.CommandLineOuterClass.Option;
import com.google.devtools.build.lib.runtime.proto.CommandLineOuterClass.OptionList;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionMetadataTag;
import com.google.devtools.common.options.OptionPriority;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsParsingResult;
import com.google.devtools.common.options.ParsedOptionDescription;
import com.google.devtools.common.options.proto.OptionFilters;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** A build event reporting the command line by which Bazel was invoked. */
public abstract class CommandLineEvent implements BuildEventWithOrderConstraint {

  @Override
  public Collection<BuildEventId> getChildrenEvents() {
    return ImmutableList.of();
  }

  @Override
  public Collection<BuildEventId> postedAfter() {
    return ImmutableList.of(BuildEventId.buildStartedId());
  }

  /** A CommandLineEvent that stores functions and values common to both Bazel command lines. */
  public abstract static class BazelCommandLineEvent extends CommandLineEvent {
    protected final String productName;
    protected final OptionsParsingResult activeStartupOptions;
    protected final String commandName;
    protected final OptionsParsingResult commandOptions;

    BazelCommandLineEvent(
        String productName,
        OptionsParsingResult activeStartupOptions,
        String commandName,
        OptionsParsingResult commandOptions) {
      this.productName = productName;
      this.activeStartupOptions = activeStartupOptions;
      this.commandName = commandName;
      this.commandOptions = commandOptions;
    }

    CommandLineSection getExecutableSection() {
      return CommandLineSection.newBuilder()
          .setSectionLabel("executable")
          .setChunkList(ChunkList.newBuilder().addChunk(productName))
          .build();
    }

    CommandLineSection getCommandSection() {
      return CommandLineSection.newBuilder()
          .setSectionLabel("command")
          .setChunkList(ChunkList.newBuilder().addChunk(commandName))
          .build();
    }

    /**
     * Convert an array of tags to the equivalent proto-generated enum values.
     *
     * <p>The proto type is duplicate in order to not burden the OptionsParser with the proto
     * dependency. A test guarantees that the two enum types are kept in sync with matching indices.
     */
    static List<OptionFilters.OptionEffectTag> getProtoEffectTags(OptionEffectTag[] tagArray) {
      ArrayList<OptionFilters.OptionEffectTag> effectTags = new ArrayList<>(tagArray.length);
      for (OptionEffectTag tag : tagArray) {
        effectTags.add(OptionFilters.OptionEffectTag.forNumber(tag.getValue()));
      }
      return effectTags;
    }

    /**
     * Convert an array of tags to the equivalent proto-generated enum values.
     *
     * <p>The proto type is duplicate in order to not burden the OptionsParser with the proto
     * dependency. A test guarantees that the two enum types are kept in sync with matching indices.
     */
    static List<OptionFilters.OptionMetadataTag> getProtoMetadataTags(
        OptionMetadataTag[] tagArray) {
      ArrayList<OptionFilters.OptionMetadataTag> metadataTags = new ArrayList<>(tagArray.length);
      for (OptionMetadataTag tag : tagArray) {
        metadataTags.add(OptionFilters.OptionMetadataTag.forNumber(tag.getValue()));
      }
      return metadataTags;
    }

    List<Option> getOptionListFromParsedOptionDescriptions(
        List<ParsedOptionDescription> parsedOptionDescriptions) {
      List<Option> options = new ArrayList<>();
      for (ParsedOptionDescription parsedOption : parsedOptionDescriptions) {
        options.add(
            createOption(
                parsedOption.getOptionDefinition(),
                parsedOption.getCommandLineForm(),
                parsedOption.getUnconvertedValue()));
      }
      return options;
    }

    private Option createOption(
        OptionDefinition optionDefinition, String combinedForm, @Nullable String value) {
      Option.Builder option = Option.newBuilder();
      option.setCombinedForm(combinedForm);
      option.setOptionName(optionDefinition.getOptionName());
      if (value != null) {
        option.setOptionValue(value);
      }
      option.addAllEffectTags(getProtoEffectTags(optionDefinition.getOptionEffectTags()));
      option.addAllMetadataTags(getProtoMetadataTags(optionDefinition.getOptionMetadataTags()));
      return option.build();
    }

    Option createStarlarkOption(String starlarkFlag, @Nullable Object value) {
      String combinedForm = String.format("--%s=%s", starlarkFlag, value);
      Option.Builder option = Option.newBuilder();
      option.setCombinedForm(combinedForm);
      option.setOptionName(starlarkFlag);
      if (value != null) {
        option.setOptionValue(String.valueOf(value));
      }
      return option.build();
    }

    /**
     * Returns the startup option section of the command line for the startup options as the server
     * received them at its startup. Since not all client options get passed to the server as
     * startup options, this might not represent the actual list of startup options as the user
     * provided them.
     */
    CommandLineSection getActiveStartupOptions() {
      return CommandLineSection.newBuilder()
          .setSectionLabel("startup options")
          .setOptionList(
              OptionList.newBuilder()
                  .addAllOption(
                      getOptionListFromParsedOptionDescriptions(
                          activeStartupOptions.asCompleteListOfParsedOptions())))
          .build();
    }

    /**
     * Returns the final part of the command line, containing whatever was left after obtaining the
     * command and its options.
     */
    CommandLineSection getResidual() {
      // Potential further split: how the residual, if any is accepted, gets interpreted depends on
      // the command. For example, for build commands, we might want to consider separating out
      // project files, as in runtime.commands.ProjectFileSupport. To properly report this, we would
      // need to let the command customize how the residual is listed. This catch-all could serve
      // as a default in this case.
      return CommandLineSection.newBuilder()
          .setSectionLabel("residual")
          .setChunkList(ChunkList.newBuilder().addAllChunk(commandOptions.getResidue()))
          .build();
    }
  }

  /** This reports a reassembled version of the command line as Bazel received it. */
  public static class OriginalCommandLineEvent extends BazelCommandLineEvent {
    public static final String LABEL = "original";
    private final Optional<List<Pair<String, String>>> originalStartupOptions;

    public OriginalCommandLineEvent(
        BlazeRuntime runtime,
        String commandName,
        OptionsParsingResult commandOptions,
        Optional<List<Pair<String, String>>> originalStartupOptions) {
      this(
          runtime.getProductName(),
          runtime.getStartupOptionsProvider(),
          commandName,
          commandOptions,
          originalStartupOptions);
    }

    @VisibleForTesting
    OriginalCommandLineEvent(
        String productName,
        OptionsParsingResult activeStartupOptions,
        String commandName,
        OptionsParsingResult commandOptions,
        Optional<List<Pair<String, String>>> originalStartupOptions) {
      super(productName, activeStartupOptions, commandName, commandOptions);
      this.originalStartupOptions = originalStartupOptions;
    }

    @Override
    public BuildEventId getEventId() {
      return BuildEventId.structuredCommandlineId(LABEL);
    }

    /**
     * Returns the literal command line options as received. These are not the final parsed values,
     * but are passed as is from the client, so we do not have the full OptionDefinition
     * information. In this form, only set the "combinedForm" field.
     */
    private CommandLineSection getStartupOptionSection() {
      if (originalStartupOptions.isPresent()) {
        List<Option> options = new ArrayList<>();
        for (Pair<String, String> sourceToOptionPair : originalStartupOptions.get()) {
          // Only add the options that were added by the command line.
          // TODO(b/19881919) decide the format that option source information should take and then
          // add all options, tagged with the source, instead of filtering out the rc options.
          if (sourceToOptionPair.first != null && sourceToOptionPair.first.isEmpty()) {
            options.add(
                Option.newBuilder().setCombinedForm(sourceToOptionPair.getSecond()).build());
          }
        }
        return CommandLineSection.newBuilder()
            .setSectionLabel("startup options")
            .setOptionList(OptionList.newBuilder().addAllOption(options))
            .build();
      } else {
        // If we were not provided with the startup options, fallback to reporting the active ones
        // stored by the Bazel Runtime.
        return getActiveStartupOptions();
      }
    }

    private CommandLineSection getExplicitCommandOptions() {
      List<ParsedOptionDescription> explicitOptions =
          commandOptions
              .asListOfExplicitOptions()
              .stream()
              .filter(
                  parsedOptionDescription ->
                      parsedOptionDescription.getPriority().getPriorityCategory()
                          == OptionPriority.PriorityCategory.COMMAND_LINE)
              .collect(Collectors.toList());
      List<Option> starlarkOptions =
          commandOptions.getStarlarkOptions().entrySet().stream()
              .map(e -> createStarlarkOption(e.getKey(), e.getValue()))
              .collect(Collectors.toList());
      return CommandLineSection.newBuilder()
          .setSectionLabel("command options")
          .setOptionList(
              OptionList.newBuilder()
                  .addAllOption(getOptionListFromParsedOptionDescriptions(explicitOptions))
                  .addAllOption(starlarkOptions))
          .build();
    }

    @Override
    public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext converters) {
      return GenericBuildEvent.protoChaining(this)
          .setStructuredCommandLine(
              CommandLine.newBuilder()
                  .setCommandLineLabel(LABEL)
                  .addSections(getExecutableSection())
                  .addSections(getStartupOptionSection())
                  .addSections(getCommandSection())
                  .addSections(getExplicitCommandOptions())
                  .addSections(getResidual())
                  .build())
          .build();
    }
  }

  /** This reports the canonical form of the command line. */
  public static class CanonicalCommandLineEvent extends BazelCommandLineEvent {
    public static final String LABEL = "canonical";

    public CanonicalCommandLineEvent(
        BlazeRuntime runtime, String commandName, OptionsParsingResult commandOptions) {
      this(
          runtime.getProductName(),
          runtime.getStartupOptionsProvider(),
          commandName,
          commandOptions);
    }

    @VisibleForTesting
    CanonicalCommandLineEvent(
        String productName,
        OptionsParsingResult activeStartupOptions,
        String commandName,
        OptionsParsingResult commandOptions) {
      super(productName, activeStartupOptions, commandName, commandOptions);
    }

    @Override
    public BuildEventId getEventId() {
      return BuildEventId.structuredCommandlineId(LABEL);
    }

    /**
     * Returns the effective startup options.
     *
     * <p>Since in this command line the command options include invocation policy's and rcs'
     * contents expanded fully, the list of startup options should prevent reapplication of these
     * contents.
     *
     * <p>The options parser does not understand the effect of these flags, since the relationship
     * between these startup options and the command options is not held within the options parser,
     * so instead, we add a small hack. Remove any explicit mentions of these flags, and explicitly
     * add the options that prevent Blaze from looking for the default rc files.
     */
    private CommandLineSection getCanonicalStartupOptions() {
      List<Option> unfilteredOptions = getActiveStartupOptions().getOptionList().getOptionList();
      // Create the fake ones to prevent reapplication of the original rc file contents.
      OptionsParser fakeOptions =
          OptionsParser.builder().optionsClasses(BlazeServerStartupOptions.class).build();
      try {
        fakeOptions.parse("--ignore_all_rc_files");
      } catch (OptionsParsingException e) {
        // Unless someone changes the definition of these flags, this is impossible.
        throw new IllegalStateException(e);
      }

      // Remove any instances of the applied, and add the new blocking ones.
      return CommandLineSection.newBuilder()
          .setSectionLabel("startup options")
          .setOptionList(
              OptionList.newBuilder()
                  .addAllOption(
                      unfilteredOptions
                          .stream()
                          .filter(
                              option -> {
                                String optionName = option.getOptionName();
                                return !optionName.equals("ignore_all_rc_files")
                                    && !optionName.equals("blazerc")
                                    && !optionName.equals("master_blazerc")
                                    && !optionName.equals("bazelrc")
                                    && !optionName.equals("master_bazelrc")
                                    && !optionName.equals("invocation_policy");
                              })
                          .collect(Collectors.toList()))
                  .addAllOption(
                      getOptionListFromParsedOptionDescriptions(
                          fakeOptions.asCompleteListOfParsedOptions())))
          .build();
    }

    /** Returns the canonical command options, overridden and default values are not listed. */
    private CommandLineSection getCanonicalCommandOptions() {
      List<Option> starlarkOptions =
          commandOptions.getStarlarkOptions().entrySet().stream()
              .map(e -> createStarlarkOption(e.getKey(), e.getValue()))
              .collect(Collectors.toList());
      return CommandLineSection.newBuilder()
          .setSectionLabel("command options")
          .setOptionList(
              OptionList.newBuilder()
                  .addAllOption(
                      getOptionListFromParsedOptionDescriptions(
                          commandOptions.asListOfCanonicalOptions()))
                  .addAllOption(starlarkOptions))
          .build();
    }

    @Override
    public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext converters) {
      return GenericBuildEvent.protoChaining(this)
          .setStructuredCommandLine(
              CommandLine.newBuilder()
                  .setCommandLineLabel(LABEL)
                  .addSections(getExecutableSection())
                  .addSections(getCanonicalStartupOptions())
                  .addSections(getCommandSection())
                  .addSections(getCanonicalCommandOptions())
                  .addSections(getResidual())
                  .build())
          .build();
    }
  }

  /**
   * A command line that Bazel accepts via flag (yes, we see the irony there).
   *
   * <p>Permits Bazel to report command lines from the tool that invoked it, if such a tool exists.
   */
  public static final class ToolCommandLineEvent extends CommandLineEvent {
    public static final String LABEL = "tool";
    private final CommandLine commandLine;

    ToolCommandLineEvent(CommandLine commandLine) {
      this.commandLine = commandLine;
    }

    @Override
    public BuildEvent asStreamProto(BuildEventContext converters) {
      return GenericBuildEvent.protoChaining(this).setStructuredCommandLine(commandLine).build();
    }

    /**
     * The label of this command line event is always "tool," so that the BuildStartingEvent
     * correctly tracks its children. The provided command line may have its own label that will be
     * more descriptive.
     */
    @Override
    public BuildEventId getEventId() {
      return BuildEventId.structuredCommandlineId(LABEL);
    }

    /**
     * The converter for the option value. We accept the command line both in base64 encoded proto
     * form and as unstructured strings.
     */
    public static class Converter
        implements com.google.devtools.common.options.Converter<ToolCommandLineEvent> {

      @Override
      public ToolCommandLineEvent convert(String input) throws OptionsParsingException {
        if (input.isEmpty()) {
          return new ToolCommandLineEvent(CommandLine.getDefaultInstance());
        }

        CommandLine commandLine;
        try {
          // Try decoding the input as a base64 encoded binary proto.
          commandLine = CommandLine.parseFrom(BaseEncoding.base64().decode(input));
        } catch (IllegalArgumentException e) {
          // If the value was not recognized as a base64-encoded proto, store the flag value as a
          // single string chunk.
          commandLine =
              CommandLine.newBuilder()
                  .setCommandLineLabel(LABEL)
                  .addSections(
                      CommandLineSection.newBuilder()
                          .setChunkList(ChunkList.newBuilder().addChunk(input)))
                  .build();
        } catch (InvalidProtocolBufferException e) {
          throw new OptionsParsingException(
              String.format("Malformed value of --experimental_tool_command_line: %s", input), e);
        }
        return new ToolCommandLineEvent(commandLine);
      }

      @Override
      public String getTypeDescription() {
        return "A command line, either as a simple string, or as a base64-encoded binary form of a"
            + " CommandLine proto";
      }
    }
  }
}
