// Copyright 2019 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.packages;

import static com.google.devtools.build.lib.packages.PackageFactory.getContext;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.docgen.annot.GlobalMethods;
import com.google.devtools.build.docgen.annot.GlobalMethods.Environment;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.packages.License.DistributionType;
import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
import com.google.devtools.build.lib.packages.Type.ConversionException;
import com.google.devtools.build.lib.server.FailureDetails.PackageLoading.Code;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.ParamType;
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.NoneType;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkFloat;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.StarlarkValue;
import net.starlark.java.eval.Structure;
import net.starlark.java.lib.json.Json;
import net.starlark.java.syntax.Location;

/**
 * A library of pre-declared Bazel Starlark functions.
 *
 * <p>For functions pre-declared in a BUILD file, use {@link #BUILD}. For Bazel functions such as
 * {@code select} and {@code depset} that are pre-declared in all BUILD, .bzl, and WORKSPACE files,
 * use {@link #COMMON}. For functions pre-declared in every Starlark file, use {@link
 * Starlark#UNIVERSE}.
 */
public final class StarlarkLibrary {

  private StarlarkLibrary() {} // uninstantiable

  /**
   * A library of Starlark values (keyed by name) that are not part of core Starlark but are common
   * to all Bazel Starlark file environments (BUILD, .bzl, WORKSPACE, and cquery). Examples: depset,
   * json.
   */
  public static final ImmutableMap<String, Object> COMMON = initCommon();

  private static ImmutableMap<String, Object> initCommon() {
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
    Starlark.addMethods(env, new DepsetLibrary());
    env.put("json", Json.INSTANCE);
    env.put("proto", Proto.INSTANCE);
    return env.buildOrThrow();
  }

  /** Proto defines the "proto" Starlark module of utilities for protocol message processing. */
  @StarlarkBuiltin(
      name = "proto",
      category = DocCategory.TOP_LEVEL_MODULE,
      doc = "A module for protocol message processing.")
  static final class Proto implements StarlarkValue {

    // Note: in due course this is likely to move to net.starlark.java.lib.proto.
    // Do not add functions that would not belong there!
    // Functions related to running the protocol compiler belong in proto_common.

    static final Proto INSTANCE = new Proto();

    @StarlarkMethod(
        name = "encode_text",
        doc =
            "Returns the struct argument's encoding as a text-format protocol message.\n"
                + "The data structure must be recursively composed of strings, ints, floats, or"
                + " bools, or structs, sequences, and dicts of these types.\n"
                + "<p>A struct is converted to a message. Fields are emitted in name order.\n"
                + "Each struct field whose value is None is ignored.\n"
                + "<p>A sequence (such as a list or tuple) is converted to a repeated field.\n"
                + "Its elements must not be sequences or dicts.\n"
                + "<p>A dict is converted to a repeated field of messages with fields named 'key'"
                + " and 'value'.\n"
                + "Entries are emitted in iteration (insertion) order.\n"
                + "The dict's keys must be strings or ints, and its values must not be sequences or"
                + " dicts.\n"
                + "Examples:<br><pre class=language-python>proto.encode_text(struct(field=123))\n"
                + "# field: 123\n\n"
                + "proto.encode_text(struct(field=True))\n"
                + "# field: true\n\n"
                + "proto.encode_text(struct(field=[1, 2, 3]))\n"
                + "# field: 1\n"
                + "# field: 2\n"
                + "# field: 3\n\n"
                + "proto.encode_text(struct(field='text', ignored_field=None))\n"
                + "# field: \"text\"\n\n"
                + "proto.encode_text(struct(field=struct(inner_field='text',"
                + " ignored_field=None)))\n"
                + "# field {\n"
                + "#   inner_field: \"text\"\n"
                + "# }\n\n"
                + "proto.encode_text(struct(field=[struct(inner_field=1),"
                + " struct(inner_field=2)]))\n"
                + "# field {\n"
                + "#   inner_field: 1\n"
                + "# }\n"
                + "# field {\n"
                + "#   inner_field: 2\n"
                + "# }\n\n"
                + "proto.encode_text(struct(field=struct(inner_field=struct(inner_inner_field='text'))))\n"
                + "# field {\n"
                + "#    inner_field {\n"
                + "#     inner_inner_field: \"text\"\n"
                + "#   }\n"
                + "# }\n\n"
                + "proto.encode_text(struct(foo={4: 3, 2: 1}))\n"
                + "# foo: {\n"
                + "#   key: 4\n"
                + "#   value: 3\n"
                + "# }\n"
                + "# foo: {\n"
                + "#   key: 2\n"
                + "#   value: 1\n"
                + "# }\n"
                + "</pre>",
        parameters = {@Param(name = "x")})
    public String encodeText(Structure x) throws EvalException {
      TextEncoder enc = new TextEncoder();
      enc.message(x);
      return enc.out.toString();
    }

    private static final class TextEncoder {

      private final StringBuilder out = new StringBuilder();
      private int indent = 0;

      // Encodes Structure x as a protocol message.
      private void message(Structure x) throws EvalException {
        // For determinism, sort fields.
        String[] fields = x.getFieldNames().toArray(new String[0]);
        Arrays.sort(fields);
        for (String field : fields) {
          try {
            field(field, x.getValue(field));
          } catch (EvalException ex) {
            throw Starlark.errorf("in %s field .%s: %s", Starlark.type(x), field, ex.getMessage());
          }
        }
      }

      // Encodes Structure field (name, v) as a message field
      // (a repeated field, if v is a dict or sequence.)
      private void field(String name, Object v) throws EvalException {
        // dict?
        if (v instanceof Dict) {
          Dict<?, ?> dict = (Dict<?, ?>) v;
          for (Map.Entry<?, ?> entry : dict.entrySet()) {
            Object key = entry.getKey();
            if (!(key instanceof String || key instanceof StarlarkInt)) {
              throw Starlark.errorf(
                  "invalid dict key: got %s, want int or string", Starlark.type(key));
            }
            emitLine(name, " {");
            indent++;
            fieldElement("key", key); // can't fail
            try {
              fieldElement("value", entry.getValue());
            } catch (EvalException ex) {
              throw Starlark.errorf(
                  "in value for dict key %s: %s", Starlark.repr(key), ex.getMessage());
            }
            indent--;
            emitLine("}");
          }
          return;
        }

        // list or tuple?
        if (v instanceof Sequence) {
          int i = 0;
          for (Object item : (Sequence<?>) v) {
            try {
              fieldElement(name, item);
            } catch (EvalException ex) {
              throw Starlark.errorf("at %s index %d: %s", Starlark.type(v), i, ex.getMessage());
            }
            i++;
          }
          return;
        }

        // non-repeated field
        if (v == Starlark.NONE) {
          return;
        }
        fieldElement(name, v);
      }

      // Emits field (name, v) as a message field, or one element of a repeated field.
      // v must be an int, float, string, bool, or Structure.
      private void fieldElement(String name, Object v) throws EvalException {
        if (v instanceof Structure) {
          emitLine(name, " {");
          indent++;
          message((Structure) v);
          indent--;
          emitLine("}");

        } else if (v instanceof String) {
          String s = (String) v;
          emitLine(
              name,
              ": \"",
              s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n"),
              "\"");

        } else if (v instanceof StarlarkInt || v instanceof Boolean) {
          emitLine(name, ": ", v.toString());
        } else if (v instanceof StarlarkFloat) {
          String s = v.toString();
          // Encoding to textproto via proto.encode_text requires "inf" for "+inf".
          if (s.equals("+inf")) {
            s = "inf";
          }
          emitLine(name, ": ", s);
        } else {
          throw Starlark.errorf(
              "got %s, want string, int, float, bool, or struct", Starlark.type(v));
        }
      }

      // Emits items on an indented line.
      private void emitLine(String... items) {
        for (int i = 0; i < indent; i++) {
          out.append("  ");
        }
        for (String item : items) {
          out.append(item);
        }
        out.append('\n');
      }
    }
  }

  @GlobalMethods(environment = {Environment.BUILD, Environment.BZL})
  private static final class DepsetLibrary {
    @StarlarkMethod(
        name = "depset",
        doc =
            "Creates a <a href=\"../builtins/depset.html\">depset</a>. The <code>direct</code>"
                + " parameter is a list of direct elements of the depset, and"
                + " <code>transitive</code> parameter is a list of depsets whose elements become"
                + " indirect elements of the created depset. The order in which elements are"
                + " returned when the depset is converted to a list is specified by the"
                + " <code>order</code> parameter. See the <a"
                + " href=\"https://bazel.build/extending/depsets\">Depsets overview</a> for more"
                + " information.\n" //
                + "<p>All"
                + " elements (direct and indirect) of a depset must be of the same type, as"
                + " obtained by the expression <code>type(x)</code>.\n" //
                + "<p>Because a hash-based set is used to eliminate duplicates during iteration,"
                + " all elements of a depset should be hashable. However, this invariant is not"
                + " currently checked consistently in all constructors. Use the"
                + " --incompatible_always_check_depset_elements flag to enable consistent"
                + " checking; this will be the default behavior in future releases;  see <a"
                + " href='https://github.com/bazelbuild/bazel/issues/10313'>Issue 10313</a>.\n" //
                + "<p>In addition, elements must currently be immutable, though this restriction"
                + " will be relaxed in future.\n" //
                + "<p> The order of the created depset should be <i>compatible</i> with the order"
                + " of its <code>transitive</code> depsets. <code>\"default\"</code> order is"
                + " compatible with any other order, all other orders are only compatible with"
                + " themselves.\n" //
                + "<p> Note on backward/forward compatibility. This function currently accepts a"
                + " positional <code>items</code> parameter. It is deprecated and will be removed"
                + " in the future, and after its removal <code>direct</code> will become a sole"
                + " positional parameter of the <code>depset</code> function. Thus, both of the"
                + " following calls are equivalent and future-proof:<br>\n" //
                + "<pre class=language-python>depset(['a', 'b'], transitive = [...])\n" //
                + "depset(direct = ['a', 'b'], transitive = [...])\n" //
                + "</pre>",
        parameters = {
          // TODO(cparsons): Make 'order' keyword-only.
          @Param(
              name = "direct",
              defaultValue = "None",
              named = true,
              allowedTypes = {
                @ParamType(type = Sequence.class),
                @ParamType(type = NoneType.class),
              },
              doc = "A list of <i>direct</i> elements of a depset. "),
          @Param(
              name = "order",
              defaultValue = "\"default\"",
              doc =
                  "The traversal strategy for the new depset. See "
                      + "<a href=\"../builtins/depset.html\">here</a> for the possible values.",
              named = true),
          @Param(
              name = "transitive",
              named = true,
              positional = false,
              allowedTypes = {
                @ParamType(type = Sequence.class, generic1 = Depset.class),
                @ParamType(type = NoneType.class),
              },
              doc = "A list of depsets whose elements will become indirect elements of the depset.",
              defaultValue = "None"),
        },
        useStarlarkThread = true)
    public Depset depset(
        Object direct, String orderString, Object transitive, StarlarkThread thread)
        throws EvalException {
      return Depset.depset(orderString, direct, transitive, thread.getSemantics());
    }
  }

  /** A starlark library supporting Bazel's implementation of the `select()` Starlark function. */
  @GlobalMethods(environment = {Environment.BUILD, Environment.BZL})
  public static final class SelectLibrary {
    @StarlarkMethod(
        name = "select",
        doc =
            "<code>select()</code> is the helper function that makes a rule attribute "
                + "<a href=\"${link common-definitions#configurable-attributes}\">"
                + "configurable</a>. See "
                + "<a href=\"${link functions#select}\">build encyclopedia</a> for details.",
        parameters = {
          @Param(
              name = "x",
              positional = true,
              doc =
                  "A dict that maps configuration conditions to values. Each key is a "
                      + "<a href=\"../builtins/Label.html\">Label</a> or a label string"
                      + " that identifies a config_setting or constraint_value instance. See the"
                      + " <a href=\"https://bazel.build/rules/macros#label-resolution\">"
                      + "documentation on macros</a> for when to use a Label instead of a string."),
          @Param(
              name = "no_match_error",
              defaultValue = "''",
              doc = "Optional custom error to report if no condition matches.",
              named = true),
        })
    public Object select(Dict<?, ?> dict, String noMatchError) throws EvalException {
      return SelectorList.select(dict, noMatchError);
    }
  }

  /**
   * A library of Starlark functions (keyed by name) pre-declared in BUILD files. A superset of
   * {@link #COMMON} (e.g. select). Excludes functions in the native module, such as exports_files.
   * Examples: environment_group, select.
   */
  public static final ImmutableMap<String, Object> BUILD = initBUILD();

  private static ImmutableMap<String, Object> initBUILD() {
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
    Starlark.addMethods(env, new BuildLibrary());
    Starlark.addMethods(env, new SelectLibrary());
    env.putAll(COMMON);
    return env.buildOrThrow();
  }

  @GlobalMethods(environment = Environment.BUILD)
  private static class BuildLibrary {
    @StarlarkMethod(
        name = "environment_group",
        doc =
            "Defines a set of related environments that can be tagged onto rules to prevent"
                + "incompatible rules from depending on each other.",
        parameters = {
          @Param(name = "name", positional = false, named = true, doc = "The name of the rule."),
          // Both parameter below are lists of label designators
          @Param(
              name = "environments",
              allowedTypes = {
                @ParamType(type = Sequence.class, generic1 = Label.class),
              },
              positional = false,
              named = true,
              doc = "A list of Labels for the environments to be grouped, from the same package."),
          @Param(
              name = "defaults",
              allowedTypes = {
                @ParamType(type = Sequence.class, generic1 = Label.class),
              },
              positional = false,
              named = true,
              doc = "A list of Labels.")
        }, // TODO(bazel-team): document what that is
        // Not documented by docgen, as this is only available in BUILD files.
        // TODO(cparsons): Devise a solution to document BUILD functions.
        documented = false,
        useStarlarkThread = true)
    public NoneType environmentGroup(
        String name,
        Sequence<?> environmentsList, // <Label>
        Sequence<?> defaultsList, // <Label>
        StarlarkThread thread)
        throws EvalException {
      PackageContext context = getContext(thread);
      List<Label> environments =
          BuildType.LABEL_LIST.convert(
              environmentsList,
              "'environment_group argument'",
              context.pkgBuilder.getLabelConverter());
      List<Label> defaults =
          BuildType.LABEL_LIST.convert(
              defaultsList, "'environment_group argument'", context.pkgBuilder.getLabelConverter());

      if (environments.isEmpty()) {
        throw Starlark.errorf("environment group %s must contain at least one environment", name);
      }
      try {
        Location loc = thread.getCallerLocation();
        context.pkgBuilder.addEnvironmentGroup(
            name, environments, defaults, context.eventHandler, loc);
        return Starlark.NONE;
      } catch (LabelSyntaxException e) {
        throw Starlark.errorf("environment group has invalid name: %s: %s", name, e.getMessage());
      } catch (Package.NameConflictException e) {
        throw Starlark.errorf("%s", e.getMessage());
      }
    }

    @StarlarkMethod(
        name = "licenses",
        doc = "Declare the license(s) for the code in the current package.",
        parameters = {
          @Param(
              name = "license_strings",
              allowedTypes = {@ParamType(type = Sequence.class, generic1 = String.class)},
              doc = "A list of strings, the names of the licenses used.")
        },
        // Not documented by docgen, as this is only available in BUILD files.
        // TODO(cparsons): Devise a solution to document BUILD functions.
        documented = false,
        useStarlarkThread = true)
    public NoneType licenses(
        Sequence<?> licensesList, // list of license strings
        StarlarkThread thread)
        throws EvalException {
      PackageContext context = getContext(thread);
      try {
        License license = BuildType.LICENSE.convert(licensesList, "'licenses' operand");
        context.pkgBuilder.setDefaultLicense(license);
      } catch (ConversionException e) {
        context.eventHandler.handle(
            Package.error(thread.getCallerLocation(), e.getMessage(), Code.LICENSE_PARSE_FAILURE));
        context.pkgBuilder.setContainsErrors();
      }
      return Starlark.NONE;
    }

    @StarlarkMethod(
        name = "distribs",
        doc = "Declare the distribution(s) for the code in the current package.",
        parameters = {@Param(name = "distribution_strings", doc = "The distributions.")},
        // Not documented by docgen, as this is only available in BUILD files.
        // TODO(cparsons): Devise a solution to document BUILD functions.
        documented = false,
        useStarlarkThread = true)
    public NoneType distribs(Object object, StarlarkThread thread) throws EvalException {
      PackageContext context = getContext(thread);

      try {
        Set<DistributionType> distribs =
            BuildType.DISTRIBUTIONS.convert(object, "'distribs' operand");
        context.pkgBuilder.setDefaultDistribs(distribs);
      } catch (ConversionException e) {
        context.eventHandler.handle(
            Package.error(
                thread.getCallerLocation(), e.getMessage(), Code.DISTRIBUTIONS_PARSE_FAILURE));
        context.pkgBuilder.setContainsErrors();
      }
      return Starlark.NONE;
    }
  }
}
