// 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();
    }

    /**
     * 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());
      return CommandLineSection.newBuilder()
          .setSectionLabel("command options")
          .setOptionList(
              OptionList.newBuilder()
                  .addAllOption(getOptionListFromParsedOptionDescriptions(explicitOptions)))
          .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.newOptionsParser(BlazeServerStartupOptions.class);
      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() {
      return CommandLineSection.newBuilder()
          .setSectionLabel("command options")
          .setOptionList(
              OptionList.newBuilder()
                  .addAllOption(
                      getOptionListFromParsedOptionDescriptions(
                          commandOptions.asListOfCanonicalOptions())))
          .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";
      }
    }
  }
}
