// Copyright 2018 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.rules.android;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.util.OS;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CompileTimeConstant;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;

/** Builder for actions that invoke the Android BusyBox. */
public final class BusyBoxActionBuilder {

  // Some flags (e.g. --mainData) may specify lists (or lists of lists) separated by special
  // characters (colon, semicolon, hashmark, ampersand) that don't work on Windows, and quoting
  // semantics are very complicated (more so than in Bash), so let's just always use a parameter
  // file.
  // TODO(laszlocsomor), TODO(corysmith): restructure the Android BusyBux's flags by deprecating
  // list-type and list-of-list-type flags that use such problematic separators in favor of
  // multi-value flags (to remove one level of listing) and by changing all list separators to a
  // platform-safe character (= comma).
  private static final ParamFileInfo FORCED_PARAM_FILE_INFO =
      ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED)
          .setUseAlways(OS.getCurrent() == OS.WINDOWS)
          .build();

  private static final ParamFileInfo WORKERS_FORCED_PARAM_FILE_INFO =
      ParamFileInfo.builder(ParameterFileType.UNQUOTED)
          .setUseAlways(true)
          .build();

  private final AndroidDataContext dataContext;
  private final NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder();
  private final ImmutableList.Builder<Artifact> outputs = ImmutableList.builder();
  private final SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder();
  private final CustomCommandLine.Builder commandLine = CustomCommandLine.builder();

  public static BusyBoxActionBuilder create(
      AndroidDataContext dataContext, @CompileTimeConstant String toolName) {
    BusyBoxActionBuilder builder = new BusyBoxActionBuilder(dataContext);
    builder.commandLine.add("--tool").add(toolName).add("--");
    return builder;
  }

  private BusyBoxActionBuilder(AndroidDataContext dataContext) {
    this.dataContext = dataContext;
  }

  /** Adds a direct input artifact. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addInput(Artifact value) {
    Preconditions.checkNotNull(value);
    commandLine.addExecPath(value);
    inputs.add(value);
    return this;
  }

  /** Adds a direct input artifact. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addInput(@CompileTimeConstant String arg, Artifact value) {
    Preconditions.checkNotNull(value);
    commandLine.addExecPath(arg, value);
    inputs.add(value);
    return this;
  }

  /**
   * Adds a series of direct input artifacts.
   *
   * <p>For efficiency, when adding a NestedSet of artifacts, use one of the transitive methods,
   * such as {@link #addTransitiveFlag(String, NestedSet, AndroidDataConverter)} and {@link
   * #addTransitiveInputValues(NestedSet)}, instead.
   *
   * @param value a string representation of the value artifacts
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addInput(
      @CompileTimeConstant String arg, String value, Iterable<Artifact> valueArtifacts) {
    commandLine.add(arg, value);
    inputs.addAll(valueArtifacts);
    return this;
  }

  /** Adds the given input artifacts without any command line options. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addInputs(Iterable<Artifact> inputs) {
    this.inputs.addAll(inputs);
    return this;
  }

  /** Adds an input artifact if it is non-null */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddInput(
      @CompileTimeConstant String arg, @Nullable Artifact value) {
    if (value != null) {
      addInput(arg, value);
    }
    return this;
  }

  /** Adds an input artifact if it is non-null */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddInput(@Nullable Artifact value) {
    if (value != null) {
      this.inputs.add(value);
    }
    return this;
  }

  /**
   * Adds a series of direct input artifacts if the list containing them is not null or empty.
   *
   * <p>For efficiency, when adding a NestedSet of artifacts, use one of the transitive methods,
   * such as {@link #addTransitiveFlag(String, NestedSet, AndroidDataConverter)} and {@link
   * #addTransitiveInputValues(NestedSet)}, instead.
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddInput(
      @CompileTimeConstant String arg, @Nullable Collection<Artifact> values) {
    if (values != null && !values.isEmpty()) {
      commandLine.addExecPaths(arg, values);
      inputs.addAll(values);
    }
    return this;
  }

  /**
   * Adds a series of direct input artifacts if the list containing them is not null or empty.
   *
   * <p>For efficiency, when adding a NestedSet of artifacts, use one of the transitive methods,
   * such as {@link #addTransitiveFlag(String, NestedSet, AndroidDataConverter)} and {@link
   * #addTransitiveInputValues(NestedSet)}, instead.
   *
   * @param value a string representation of the value artifacts
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddInput(
      @CompileTimeConstant String arg,
      String value,
      @Nullable Collection<Artifact> valueArtifacts) {
    if (valueArtifacts != null && !valueArtifacts.isEmpty()) {
      addInput(arg, value, valueArtifacts);
    }
    return this;
  }

  /** Adds an output artifact */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addOutput(@CompileTimeConstant String arg, Artifact value) {
    Preconditions.checkNotNull(value);
    commandLine.addExecPath(arg, value);
    outputs.add(value);
    return this;
  }

  /** Adds the given output artifacts without adding any command line options. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addOutputs(Iterable<Artifact> outputs) {
    this.outputs.addAll(outputs);
    return this;
  }

  /** Adds an output artifact if it is non-null */
  public BusyBoxActionBuilder maybeAddOutput(
      @CompileTimeConstant String arg, @Nullable Artifact value) {
    if (value != null) {
      return addOutput(arg, value);
    }
    return this;
  }

  /**
   * Adds a series of transitive input artifacts.
   *
   * <p>These artifacts will not be mentioned on the command line - use {@link
   * #addTransitiveFlag(String, NestedSet, AndroidDataConverter)} for that.
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addTransitiveInputValues(NestedSet<Artifact> values) {
    inputs.addTransitive(values);
    return this;
  }

  /**
   * Adds an efficient flag based on transitive values.
   *
   * <p>The flag will only be specified once, followed by the joined values specified by the
   * converter, for example: --flag value1,value2
   *
   * <p>The values will only be collapsed and turned into a flag at execution time.
   *
   * <p>The values will not be added as inputs - use {@link #addTransitiveInputValues(NestedSet)}
   * for that.
   */
  @CanIgnoreReturnValue
  public <T> BusyBoxActionBuilder addTransitiveFlag(
      @CompileTimeConstant String arg,
      NestedSet<? extends T> transitiveValues,
      AndroidDataConverter<T> converter) {
    commandLine.addAll(arg, converter.getVectorArg(transitiveValues));
    return this;
  }

  /**
   * Adds an efficient flag based on transitive values.
   *
   * <p>Each transitive value, as created using the converter, will be proceeded by the flag, for
   * example: --flag value1 --flag value2
   *
   * <p>The values will only be collapsed and turned into a flag at execution time.
   *
   * <p>The values will not be added as inputs - use {@link #addTransitiveInputValues(NestedSet)}
   * for that.
   */
  @CanIgnoreReturnValue
  public <T> BusyBoxActionBuilder addTransitiveFlagForEach(
      @CompileTimeConstant String arg,
      NestedSet<? extends T> transitiveValues,
      AndroidDataConverter<T> converter) {
    commandLine.addAll(converter.getVectorArgForEach(arg, transitiveValues));
    return this;
  }

  /**
   * Adds an efficient flag and inputs based on transitive values.
   *
   * <p>Each value will be separated on the command line by the ':' character, the option parser's
   * PathListConverter delimiter.
   *
   * <p>Unlike other transitive input methods in this class, this method adds the values to both the
   * command line and the list of inputs.
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addTransitiveVectoredInput(
      @CompileTimeConstant String arg, NestedSet<Artifact> values) {
    commandLine.addExecPaths(arg, VectorArg.join(":").each(values));
    inputs.addTransitive(values);
    return this;
  }

  /** Adds a flag with a value set to the current target's label */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addLabelFlag(@CompileTimeConstant String arg) {
    commandLine.addLabel(arg, dataContext.getLabel());
    return this;
  }

  /** Adds a flag with no arguments to the command line. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addFlag(@CompileTimeConstant String value) {
    commandLine.add(value);
    return this;
  }

  /** Adds a flag with a String value to the command line. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addFlag(@CompileTimeConstant String arg, String value) {
    Preconditions.checkNotNull(value);
    commandLine.add(arg, value);
    return this;
  }

  /** If the condition is true, adds a flag with no arguments to the command line. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddFlag(@CompileTimeConstant String arg, boolean condition) {
    if (condition) {
      commandLine.add(arg);
    }
    return this;
  }

  /** If the flag is a non-null, non-empty String, adds the flag and value to the command line. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddFlag(
      @CompileTimeConstant String arg, @Nullable String value) {
    if (value != null && !value.isEmpty()) {
      addFlag(arg, value);
    }
    return this;
  }

  /**
   * Efficiently adds a flag and a list of values to the command line.
   *
   * <p>The values will be joined in execution and separated by commas.
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addVectoredFlag(
      @CompileTimeConstant String arg, List<String> values) {
    Preconditions.checkNotNull(values);
    commandLine.addAll(arg, VectorArg.join(",").each(values));

    return this;
  }

  /**
   * If the values are not null or empty, efficiently adds a flag with them to the command line.
   *
   * <p>The values will be joined in execution and separated by commas.
   */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder maybeAddVectoredFlag(
      @CompileTimeConstant String arg, @Nullable List<String> values) {
    if (values != null && !values.isEmpty()) {
      addVectoredFlag(arg, values);
    }
    return this;
  }

  /** Adds aapt to the command line and inputs. */
  @CanIgnoreReturnValue
  public BusyBoxActionBuilder addAapt() {
    FilesToRunProvider aapt2 = dataContext.getSdk().getAapt2();
    commandLine.addExecPath("--aapt2", aapt2.getExecutable());
    spawnActionBuilder.addTool(aapt2);
    return this;
  }

  /** Adds the Android JAR from the SDK to the command line and inputs */
  public BusyBoxActionBuilder addAndroidJar() {
    return addInput("--androidJar", dataContext.getSdk().getAndroidJar());
  }

  /**
   * Builds and registers this action.
   *
   * @param message a progress message (visible in Bazel output), for example "Running tool". The
   *     current label will be appended to this message.
   * @param mnemonic a mnemonic used to indicate the tool being run, for example, "BusyBoxTool".
   */
  public void buildAndRegister(String message, String mnemonic) {
    spawnActionBuilder
        .useDefaultShellEnvironment()
        .addTransitiveInputs(inputs.build())
        .addOutputs(outputs.build())
        .setExecutable(dataContext.getBusybox())
        .setProgressMessage("%s for %s", message, dataContext.getLabel())
        .setMnemonic(mnemonic);

    ImmutableMap.Builder<String, String> executionInfo = ImmutableMap.builder();
    executionInfo.putAll(dataContext.getExecutionInfo());

    if (dataContext.isPersistentBusyboxToolsEnabled()) {
      commandLine.add("--logWarnings=false");
      spawnActionBuilder.addCommandLine(commandLine.build(), WORKERS_FORCED_PARAM_FILE_INFO);
      executionInfo.putAll(ExecutionRequirements.WORKER_MODE_ENABLED);
    } else {
      spawnActionBuilder.addCommandLine(commandLine.build(), FORCED_PARAM_FILE_INFO);
    }

    spawnActionBuilder.setExecutionInfo(executionInfo.buildOrThrow());

    dataContext.registerAction(spawnActionBuilder);
  }
}
