// 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.buildtool;

import static com.google.common.collect.ImmutableMap.toImmutableMap;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.AnalysisOptions;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.buildeventstream.BuildEventProtocolOptions;
import com.google.devtools.build.lib.exec.ExecutionOptions;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.pkgcache.PackageOptions;
import com.google.devtools.build.lib.runtime.KeepGoingOption;
import com.google.devtools.build.lib.runtime.LoadingPhaseThreadsOption;
import com.google.devtools.build.lib.runtime.UiOptions;
import com.google.devtools.build.lib.server.FailureDetails.Analysis;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.OptionsUtils;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingResult;
import com.google.devtools.common.options.OptionsProvider;
import com.google.devtools.common.options.ParsedOptionDescription;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
 * A BuildRequest represents a single invocation of the build tool by a user.
 * A request specifies a list of targets to be built for a single
 * configuration, a pair of output/error streams, and additional options such
 * as --keep_going, --jobs, etc.
 */
public class BuildRequest implements OptionsProvider {
  public static final String VALIDATION_ASPECT_NAME = "ValidateTarget";

  private static final ImmutableList<Class<? extends OptionsBase>> MANDATORY_OPTIONS =
      ImmutableList.of(
          BuildRequestOptions.class,
          PackageOptions.class,
          BuildLanguageOptions.class,
          LoadingOptions.class,
          AnalysisOptions.class,
          ExecutionOptions.class,
          KeepGoingOption.class,
          LoadingPhaseThreadsOption.class);

  /** Returns a new Builder instance. */
  public static Builder builder() {
    return new Builder();
  }

  /** A Builder class to help create instances of BuildRequest. */
  public static final class Builder {
    private UUID id;
    private OptionsParsingResult options;
    private OptionsParsingResult startupOptions;
    private String commandName;
    private OutErr outErr;
    private List<String> targets;
    private long startTimeMillis; // milliseconds since UNIX epoch.
    private boolean needsInstrumentationFilter;
    private boolean runTests;
    private boolean checkForActionConflicts = true;
    private boolean reportIncompatibleTargets = true;

    private Builder() {}

    @CanIgnoreReturnValue
    public Builder setId(UUID id) {
      this.id = id;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setOptions(OptionsParsingResult options) {
      this.options = options;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setStartupOptions(OptionsParsingResult startupOptions) {
      this.startupOptions = startupOptions;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setCommandName(String commandName) {
      this.commandName = commandName;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setOutErr(OutErr outErr) {
      this.outErr = outErr;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setTargets(List<String> targets) {
      this.targets = targets;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setStartTimeMillis(long startTimeMillis) {
      this.startTimeMillis = startTimeMillis;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setNeedsInstrumentationFilter(boolean needsInstrumentationFilter) {
      this.needsInstrumentationFilter = needsInstrumentationFilter;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setRunTests(boolean runTests) {
      this.runTests = runTests;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setCheckforActionConflicts(boolean checkForActionConflicts) {
      this.checkForActionConflicts = checkForActionConflicts;
      return this;
    }

    /**
     * If true, build status depends on whether or not requested targets are platform-compatible
     * ({@link com.google.devtools.build.lib.analysis.IncompatiblePlatformProvider}). If false, this
     * doesn't matter.
     *
     * <p>This should be true for builds (where users care if their targets produce meaningful
     * output) and false for queries (where users want to understand target relationships or
     * diagnose why incompatible targets are incompatible).
     */
    @CanIgnoreReturnValue
    public Builder setReportIncompatibleTargets(boolean report) {
      this.reportIncompatibleTargets = report;
      return this;
    }

    public BuildRequest build() {
      return new BuildRequest(
          commandName,
          options,
          startupOptions,
          targets,
          outErr,
          id,
          startTimeMillis,
          needsInstrumentationFilter,
          runTests,
          checkForActionConflicts,
          reportIncompatibleTargets);
    }
  }

  private final UUID id;
  private final LoadingCache<Class<? extends OptionsBase>, Optional<OptionsBase>> optionsCache;
  private final Map<String, Object> starlarkOptions;

  /** A human-readable description of all the non-default option settings. */
  private final String optionsDescription;

  /**
   * The name of the Blaze command that the user invoked.
   * Used for --announce.
   */
  private final String commandName;

  private final OutErr outErr;
  private final List<String> targets;

  private final long startTimeMillis; // milliseconds since UNIX epoch.

  private final boolean needsInstrumentationFilter;
  private final boolean runningInEmacs;
  private final boolean runTests;
  private final boolean checkForActionConflicts;
  private final boolean reportIncompatibleTargets;

  private BuildRequest(
      String commandName,
      final OptionsParsingResult options,
      final OptionsParsingResult startupOptions,
      List<String> targets,
      OutErr outErr,
      UUID id,
      long startTimeMillis,
      boolean needsInstrumentationFilter,
      boolean runTests,
      boolean checkForActionConflicts,
      boolean reportIncompatibleTargets) {
    this.commandName = commandName;
    this.optionsDescription = OptionsUtils.asShellEscapedString(options);
    this.outErr = outErr;
    this.targets = targets;
    this.id = id;
    this.startTimeMillis = startTimeMillis;
    this.optionsCache =
        Caffeine.newBuilder()
            .build(
                key -> {
                  OptionsBase result = options.getOptions(key);
                  if (result == null && startupOptions != null) {
                    result = startupOptions.getOptions(key);
                  }

                  return Optional.fromNullable(result);
                });
    this.starlarkOptions = options.getStarlarkOptions();
    this.needsInstrumentationFilter = needsInstrumentationFilter;
    this.runTests = runTests;
    this.checkForActionConflicts = checkForActionConflicts;
    this.reportIncompatibleTargets = reportIncompatibleTargets;

    for (Class<? extends OptionsBase> optionsClass : MANDATORY_OPTIONS) {
      Preconditions.checkNotNull(getOptions(optionsClass));
    }

    // All this, just to pass a global boolean from the client to the server. :(
    this.runningInEmacs = options.getOptions(UiOptions.class).runningInEmacs;
  }

  /**
   * Return whether this BuildRequest contains multiple top-level configs
   *
   * <p>Note: The ability to have a multi-top-level-config build is currently completely disabled.
   * However, certain parts of the infra would fail horribly if it was ever enabled at all so
   * keeping this flag for those parts to check as a sort of mild future-proofing.
   */
  public boolean isMultiConfigBuild() {
    return false;
  }

  /**
   * Since the OptionsProvider interface is used by many teams, this method is String-keyed even
   * though it should always contain labels for our purposes. Consumers of this method should
   * probably use the {@link BuildOptions#labelizeStarlarkOptions} method before doing meaningful
   * work with the results.
   */
  @Override
  public Map<String, Object> getStarlarkOptions() {
    return starlarkOptions;
  }

  @Override
  public Map<String, Object> getExplicitStarlarkOptions(
      Predicate<? super ParsedOptionDescription> filter) {
    throw new UnsupportedOperationException("No known callers to this implementation");
  }

  /**
   * Returns a unique identifier that universally identifies this build.
   */
  public UUID getId() {
    return id;
  }

  /**
   * Returns the name of the Blaze command that the user invoked.
   */
  public String getCommandName() {
    return commandName;
  }

  boolean isRunningInEmacs() {
    return runningInEmacs;
  }

  /**
   * Returns true if tests should be run by the build tool.
   */
  public boolean shouldRunTests() {
    return runTests;
  }

  /**
   * Returns the (immutable) list of targets to build in commandline
   * form.
   */
  public List<String> getTargets() {
    return targets;
  }

  /**
   * Returns the output/error streams to which errors and progress messages
   * should be sent during the fulfillment of this request.
   */
  public OutErr getOutErr() {
    return outErr;
  }

  @Override
  @SuppressWarnings("unchecked")
  public <T extends OptionsBase> T getOptions(Class<T> clazz) {
    return (T) optionsCache.get(clazz).orNull();
  }


  /**
   * Returns the set of command-line options specified for this request.
   */
  public BuildRequestOptions getBuildOptions() {
    return getOptions(BuildRequestOptions.class);
  }

  /** Returns the set of options related to the loading phase. */
  public PackageOptions getPackageOptions() {
    return getOptions(PackageOptions.class);
  }

  /**
   * Returns the set of options related to the loading phase.
   */
  public LoadingOptions getLoadingOptions() {
    return getOptions(LoadingOptions.class);
  }

  /**
   * Returns the set of command-line options related to the view specified for
   * this request.
   */
  public AnalysisOptions getViewOptions() {
    return getOptions(AnalysisOptions.class);
  }

  /** Returns the value of the --keep_going option. */
  public boolean getKeepGoing() {
    return getOptions(KeepGoingOption.class).keepGoing;
  }

  /** Returns the value of the --loading_phase_threads option. */
  int getLoadingPhaseThreadCount() {
    return getOptions(LoadingPhaseThreadsOption.class).threads;
  }
  /**
   * Returns the set of execution options specified for this request.
   */
  public ExecutionOptions getExecutionOptions() {
    return getOptions(ExecutionOptions.class);
  }

  /**
   * Returns the human-readable description of the non-default options
   * for this build request.
   */
  public String getOptionsDescription() {
    return optionsDescription;
  }

  /**
   * Return the time (according to System.currentTimeMillis()) at which the
   * service of this request was started.
   */
  public long getStartTime() {
    return startTimeMillis;
  }

  public boolean needsInstrumentationFilter() {
    return needsInstrumentationFilter;
  }

  /**
   * Validates the options for this BuildRequest.
   *
   * <p>Issues warnings or throws {@code InvalidConfigurationException} for option settings that
   * conflict.
   *
   * @return list of warnings
   */
  public List<String> validateOptions() {
    List<String> warnings = new ArrayList<>();

    int localTestJobs = getExecutionOptions().localTestJobs;
    int jobs = getBuildOptions().jobs;
    if (localTestJobs > jobs) {
      warnings.add(
          String.format("High value for --local_test_jobs: %d. This exceeds the value for --jobs: "
              + "%d. Only up to %d local tests will run concurrently.", localTestJobs, jobs, jobs));
    }

    // Validate other BuildRequest options.
    if (getBuildOptions().verboseExplanations && getBuildOptions().explanationPath == null) {
      warnings.add("--verbose_explanations has no effect when --explain=<file> is not enabled");
    }

    return warnings;
  }

  /** Creates a new TopLevelArtifactContext from this build request. */
  public TopLevelArtifactContext getTopLevelArtifactContext() {
    BuildRequestOptions buildOptions = getBuildOptions();
    return new TopLevelArtifactContext(
        getOptions(ExecutionOptions.class).testStrategy.equals("exclusive"),
        getOptions(BuildEventProtocolOptions.class).expandFilesets,
        getOptions(BuildEventProtocolOptions.class).fullyResolveFilesetSymlinks,
        OutputGroupInfo.determineOutputGroups(
            buildOptions.outputGroups, validationMode(), /*shouldRunTests=*/ shouldRunTests()));
  }

  public ImmutableList<String> getAspects() {
    List<String> aspects = getBuildOptions().aspects;
    ImmutableList.Builder<String> result = ImmutableList.<String>builder().addAll(aspects);
    if (!aspects.contains(VALIDATION_ASPECT_NAME) && useValidationAspect()) {
      result.add(VALIDATION_ASPECT_NAME);
    }
    return result.build();
  }

  @Nullable
  public ImmutableMap<String, String> getAspectsParameters() throws ViewCreationFailedException {
    List<Map.Entry<String, String>> aspectsParametersList = getBuildOptions().aspectsParameters;
    try {
      return aspectsParametersList.stream()
          .collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
    } catch (IllegalArgumentException e) {
      String errorMessage = "Error in top-level aspects parameters";
      throw new ViewCreationFailedException(
          errorMessage,
          FailureDetail.newBuilder()
              .setMessage(errorMessage)
              .setAnalysis(Analysis.newBuilder().setCode(Analysis.Code.ASPECT_CREATION_FAILED))
              .build(),
          e);
    }
  }

  /** Whether {@value #VALIDATION_ASPECT_NAME} is in use. */
  public boolean useValidationAspect() {
    return validationMode() == OutputGroupInfo.ValidationMode.ASPECT;
  }

  private OutputGroupInfo.ValidationMode validationMode() {
    BuildRequestOptions buildOptions = getBuildOptions();
    if (!buildOptions.runValidationActions) {
      return OutputGroupInfo.ValidationMode.OFF;
    }
    return buildOptions.useValidationAspect
        ? OutputGroupInfo.ValidationMode.ASPECT
        : OutputGroupInfo.ValidationMode.OUTPUT_GROUP;
  }

  public boolean getCheckForActionConflicts() {
    return checkForActionConflicts;
  }

  public boolean reportIncompatibleTargets() {
    return reportIncompatibleTargets;
  }
}
