// 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.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.rules.android.AndroidConfiguration.AndroidAaptVersion;
import com.google.devtools.build.lib.util.OS;
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. */
  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
   */
  public BusyBoxActionBuilder addInput(
      @CompileTimeConstant String arg, String value, Iterable<Artifact> valueArtifacts) {
    Preconditions.checkState(
        !(valueArtifacts instanceof NestedSet),
        "NestedSet values should not be added here, since they will be inefficiently collapsed in"
            + " analysis time. Use one of the transitive input methods instead.");
    commandLine.add(arg, value);
    inputs.addAll(valueArtifacts);
    return this;
  }

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

  /** Adds an input artifact if it is non-null */
  public BusyBoxActionBuilder maybeAddInput(
      @CompileTimeConstant String arg, @Nullable Artifact value) {
    if (value != null) {
      addInput(arg, 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.
   */
  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
   */
  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 */
  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. */
  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.
   */
  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.
   */
  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.
   */
  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 host-specific path separator.
   *
   * <p>Unlike other transitive input methods in this class, this method adds the values to both the
   * command line and the list of inputs.
   */
  public BusyBoxActionBuilder addTransitiveVectoredInput(
      @CompileTimeConstant String arg, NestedSet<Artifact> values) {
    commandLine.addExecPaths(
        arg,
        VectorArg.join(
                dataContext
                    .getActionConstructionContext()
                    .getConfiguration()
                    .getHostPathSeparator())
            .each(values));
    inputs.addTransitive(values);
    return this;
  }

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

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

  /** Adds a flag with a String value to the command line. */
  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. */
  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. */
  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.
   */
  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.
   */
  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. */
  public BusyBoxActionBuilder addAapt(AndroidAaptVersion aaptVersion) {
    FilesToRunProvider aapt;
    if (aaptVersion == AndroidAaptVersion.AAPT2) {
      aapt = dataContext.getSdk().getAapt2();
      commandLine.addExecPath("--aapt2", aapt.getExecutable());
    } else {
      aapt = dataContext.getSdk().getAapt();
      commandLine.addExecPath("--aapt", aapt.getExecutable());
    }

    spawnActionBuilder.addTool(aapt);

    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);

    if (dataContext.isPersistentBusyboxToolsEnabled()) {
      spawnActionBuilder
          .setExecutionInfo(ExecutionRequirements.WORKER_MODE_ENABLED)
          .addCommandLine(commandLine.build(), WORKERS_FORCED_PARAM_FILE_INFO);
    } else {
      spawnActionBuilder.addCommandLine(commandLine.build(), FORCED_PARAM_FILE_INFO);
    }

    dataContext.registerAction(spawnActionBuilder);
  }
}
