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

import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import java.io.IOException;
import javax.annotation.Nullable;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkSemantics;
import net.starlark.java.eval.StarlarkValue;

/** Interface for actions in Starlark. */
@StarlarkBuiltin(
    name = "Action",
    category = DocCategory.BUILTIN,
    doc =
        "An action created during rule analysis.<p>This object is visible for the purpose of"
            + " testing, and may be obtained from an <code>Actions</code> provider. It is normally"
            + " not necessary to access <code>Action</code> objects or their fields within a rule's"
            + " implementation function. You may instead want to see the <a"
            + " href='https://bazel.build/extending/rules#actions'>Rules page</a> for a general"
            + " discussion of how to use actions when defining custom rules, or the <a"
            + " href='../builtins/actions.html'>API reference</a> for creating actions.<p>Some"
            + " fields of this object are only applicable for certain kinds of actions. Fields that"
            + " are inapplicable are set to <code>None</code>.")
public interface ActionApi extends StarlarkValue {

  @StarlarkMethod(name = "mnemonic", structField = true, doc = "The mnemonic for this action.")
  String getMnemonic();

  @StarlarkMethod(
      name = "inputs",
      doc = "A set of the input files of this action.",
      structField = true)
  Depset getStarlarkInputs();

  @StarlarkMethod(
      name = "outputs",
      doc = "A set of the output files of this action.",
      structField = true)
  Depset getStarlarkOutputs();

  @StarlarkMethod(
      name = "argv",
      doc =
          "For actions created by <a href=\"../builtins/actions.html#run\">ctx.actions.run()</a> or"
              + " <a href=\"../builtins/actions.html#run_shell\">ctx.actions.run_shell()</a>  an"
              + " immutable list of the arguments for the command line to be executed. Note that"
              + " for shell actions the first two arguments will be the shell path and"
              + " <code>\"-c\"</code>.",
      structField = true,
      allowReturnNones = true)
  @Nullable
  Sequence<String> getStarlarkArgv() throws EvalException, InterruptedException;

  @StarlarkMethod(
      name = "args",
      doc =
          "A list of frozen <a href=\"../builtins/Args.html\">Args</a> objects containing"
              + " information about the action arguments. These objects contain accurate argument"
              + " information, including arguments involving expanded action output directories."
              + " However, <a href=\"../builtins/Args.html\">Args</a> objects are not readable in"
              + " the analysis phase. For a less accurate account of arguments which is available"
              + " in the analysis phase, see <a href=\"#argv\">argv</a>. <p>Note that some types of"
              + " actions do not yet support exposure of this field. For such action types, this is"
              + " <code>None</code>.",
      structField = true,
      allowReturnNones = true)
  @Nullable
  Sequence<CommandLineArgsApi> getStarlarkArgs() throws EvalException, InterruptedException;

  /**
   * If the action writes a file whose content is known at analysis time, returns that content;
   * returns null otherwise.
   *
   * <p>The content might be unknown if, for instance, the action expands an {@code Args} object
   * that includes a directory ({@link TreeArtifact}) with {@code expand_directories=False}.
   *
   * @throws EvalException if there is a Starlark evaluation error, e.g. in an {@code Args} object's
   *     call to a {@code map_each} callback.
   * @throws IOException if there is a non-Starlark error in expanding an {@code Args} object.
   */
  @StarlarkMethod(
      name = "content",
      doc =
          "For actions created by <a"
              + " href=\"../builtins/actions.html#write\">ctx.actions.write()</a> or <a"
              + " href=\"../builtins/actions.html#expand_template\">ctx.actions.expand_template()</a>,"
              + " the contents of the file to be written, if those contents can be computed during "
              + " the analysis phase. The value is <code>None</code> if the contents cannot be"
              + " determined until the execution phase, such as when a directory in an <a"
              + " href=\"../builtins/Args.html\">Args</a> object needs to be expanded.",
      structField = true,
      allowReturnNones = true)
  @Nullable
  String getStarlarkContent() throws IOException, EvalException, InterruptedException;

  @StarlarkMethod(
      name = "substitutions",
      doc =
          "For actions created by <a"
              + " href=\"../builtins/actions.html#expand_template\">ctx.actions.expand_template()</a>,"
              + " an immutable dict holding the substitution mapping.",
      structField = true,
      allowReturnNones = true)
  @Nullable
  Dict<String, String> getStarlarkSubstitutions() throws EvalException;

  @StarlarkMethod(
      name = "env",
      structField = true,
      useStarlarkSemantics = true,
      doc =
          "The 'fixed' environment variables for this action. This includes only environment"
              + " settings which are explicitly set by the action definition, and thus omits"
              + " settings which are only pre-set in the execution environment.")
  Dict<String, String> getEnv(StarlarkSemantics semantics) throws EvalException;

  @StarlarkMethod(
      name = "execution_info",
      structField = true,
      doc =
          "The execution requirements for this action, set for this action specifically. This is a"
              + " dictionary that maps strings specifying execution info to arbitrary strings."
              + " This is in order to match the structure of execution info in other parts of the"
              + " code base; all relevant info is in the keyset. Returns None if this action does"
              + " not expose execution requirements.",
      allowReturnNones = true,
      enableOnlyWithFlag = BuildLanguageOptions.EXPERIMENTAL_GOOGLE_LEGACY_API)
  @Nullable
  public Dict<String, String> getExecutionInfoDict();
}
