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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import java.util.Collection;
import javax.annotation.Nullable;

/**
 * A generic, type-safe {@link NestedSet} wrapper for Skylark.
 *
 * <p>The content type of a {@code SkylarkNestedSet} is the intersection of the {@link SkylarkType}
 * of each of its elements. It is an error if this intersection is {@link SkylarkType#BOTTOM}. An
 * empty set has a content type of {@link SkylarkType#TOP}.
 *
 * <p>It is also an error if this type has a non-bottom intersection with {@link SkylarkType#DICT}
 * or {@link SkylarkType#LIST}, unless the set is empty.
 *
 * <p>TODO(bazel-team): Decide whether this restriction is still useful.
 */
@SkylarkModule(
  name = "depset",
  category = SkylarkModuleCategory.BUILTIN,
  doc =
      "<p>A specialized data structure that supports efficient merge operations and has a defined "
          + "traversal order. Commonly used for accumulating data from transitive dependencies in "
          + "rules and aspects. For more information see <a href=\"../depsets.md\">here</a>."
          + "<p>"
          + "Depsets are not implemented as hash sets and do not support fast membership tests. If "
          + "you need a general set datatype, you can simulate one using a dictionary where all "
          + "keys map to <code>None</code>."
          + "<p>"
          + "Depsets are immutable. They should be created using their "
          + "<a href=\"globals.html#depset\">constructor function</a> and merged or augmented with "
          + "other depsets via the <code>transitive</code> argument. There are other deprecated "
          + "methods (<code>|</code> and <code>+</code> operators, <code>union</code> method) that "
          + "will eventually go away."
          + "<p>"
          + "The <code>order</code> parameter determines the kind of traversal that is done to "
          + "convert the depset to an iterable. There are four possible values:"
          + "<ul>"
          + "<li><code>\"default\"</code> (formerly <code>\"stable\"</code>): Order is unspecified "
          + "(but deterministic).</li>"
          + "<li><code>\"postorder\"</code> (formerly <code>\"compile\"</code>): A left-to-right "
          + "post-ordering. Precisely, this recursively traverses all children leftmost-first, "
          + "then the direct elements leftmost-first.</li>"
          + "<li><code>\"preorder\"</code> (formerly <code>\"naive_link\"</code>): A left-to-right "
          + "pre-ordering. Precisely, this traverses the direct elements leftmost-first, then "
          + "recursively traverses the children leftmost-first.</li>"
          + "<li><code>\"topological\"</code> (formerly <code>\"link\"</code>): A topological "
          + "ordering from the root down to the leaves. There is no left-to-right guarantee.</li>"
          + "</ul>"
          + "<p>"
          + "Two depsets may only be merged if either both depsets have the same order, or one of "
          + "them has <code>\"default\"</code> order. In the latter case the resulting depset's "
          + "order will be the same as the other's order."
          + "<p>"
          + "Depsets may contain duplicate values but these will be suppressed when iterating "
          + "(using <code>to_list()</code>). Duplicates may interfere with the ordering semantics."
)
@Immutable
@AutoCodec
public final class SkylarkNestedSet implements SkylarkValue, SkylarkQueryable {
  private final SkylarkType contentType;
  private final NestedSet<?> set;
  @Nullable private final ImmutableList<Object> items;
  @Nullable private final ImmutableList<NestedSet<?>> transitiveItems;

  @AutoCodec.VisibleForSerialization
  SkylarkNestedSet(
      SkylarkType contentType,
      NestedSet<?> set,
      ImmutableList<Object> items,
      ImmutableList<NestedSet<?>> transitiveItems) {
    this.contentType = Preconditions.checkNotNull(contentType, "type cannot be null");
    this.set = set;
    this.items = items;
    this.transitiveItems = transitiveItems;
  }

  static SkylarkNestedSet of(
      Order order,
      SkylarkType contentType,
      Object item,
      Location loc,
      @Nullable SkylarkNestedSet left)
      throws EvalException {
    ImmutableList.Builder<Object> itemsBuilder = ImmutableList.builder();
    ImmutableList.Builder<NestedSet<?>> transitiveItemsBuilder = ImmutableList.builder();
    if (left != null) {
      if (left.items == null) { // SkylarkSet created from native NestedSet
        transitiveItemsBuilder.add(left.set);
      } else { // Preserving the left-to-right addition order.
        itemsBuilder.addAll(left.items);
        transitiveItemsBuilder.addAll(left.transitiveItems);
      }
    }
    // Adding the item
    if (item instanceof SkylarkNestedSet) {
      SkylarkNestedSet nestedSet = (SkylarkNestedSet) item;
      if (!nestedSet.isEmpty()) {
        contentType = getTypeAfterInsert(
            contentType, nestedSet.contentType, /*lastInsertedType=*/ null, loc);
        transitiveItemsBuilder.add(nestedSet.set);
      }
    } else if (item instanceof SkylarkList) {
      SkylarkType lastInsertedType = null;
      // TODO(bazel-team): we should check ImmutableList here but it screws up genrule at line 43
      for (Object object : (SkylarkList) item) {
        SkylarkType elemType = SkylarkType.of(object.getClass());
        contentType = getTypeAfterInsert(contentType, elemType, lastInsertedType, loc);
        lastInsertedType = elemType;
        checkImmutable(object, loc);
        itemsBuilder.add(object);
      }
    } else {
      throw new EvalException(
          loc,
          String.format(
              "cannot union value of type '%s' to a depset", EvalUtils.getDataTypeName(item)));
    }
    ImmutableList<Object> items = itemsBuilder.build();
    ImmutableList<NestedSet<?>> transitiveItems = transitiveItemsBuilder.build();
    // Initializing the real nested set
    NestedSetBuilder<Object> builder = new NestedSetBuilder<>(order);
    builder.addAll(items);
    try {
      for (NestedSet<?> nestedSet : transitiveItems) {
        builder.addTransitive(nestedSet);
      }
    } catch (IllegalArgumentException e) {
      // Order mismatch between item and builder.
      throw new EvalException(loc, e.getMessage());
    }
    return new SkylarkNestedSet(contentType, builder.build(), items, transitiveItems);
  }

  public static SkylarkNestedSet of(Order order, Object item, Location loc) throws EvalException {
    return of(order, SkylarkType.TOP, item, loc, null);
  }

  public static SkylarkNestedSet of(SkylarkNestedSet left, Object right, Location loc)
      throws EvalException {
    return of(left.set.getOrder(), left.contentType, right, loc, left);
  }

  /**
   * Returns a type safe SkylarkNestedSet. Use this instead of the constructor if possible.
   */
  public static <T> SkylarkNestedSet of(SkylarkType contentType, NestedSet<T> set) {
    return new SkylarkNestedSet(contentType, set, null, null);
  }

  /**
   * Returns a type safe SkylarkNestedSet. Use this instead of the constructor if possible.
   */
  public static <T> SkylarkNestedSet of(Class<T> contentType, NestedSet<T> set) {
    return of(SkylarkType.of(contentType), set);
  }

  private static final SkylarkType DICT_LIST_UNION =
      SkylarkType.Union.of(SkylarkType.DICT, SkylarkType.LIST);

  /**
   * Checks that an item type is allowed in a given set type, and returns the type of a new depset
   * with that item inserted.
   */
  private static SkylarkType getTypeAfterInsert(
      SkylarkType depsetType, SkylarkType itemType, SkylarkType lastInsertedType, Location loc)
      throws EvalException {
    if (lastInsertedType != null && lastInsertedType.equals(itemType)) {
      // Fast path, type shoudln't have changed, so no need to check.
      // TODO(bazel-team): Make skylark type checking less expensive.
      return depsetType;
    }

    // Check not dict or list.
    if (SkylarkType.intersection(DICT_LIST_UNION, itemType) != SkylarkType.BOTTOM) {
      throw new EvalException(
          loc, String.format("depsets cannot contain items of type '%s'", itemType));
    }

    // Check compatible.
    SkylarkType resultType = SkylarkType.intersection(depsetType, itemType);
    if (resultType == SkylarkType.BOTTOM) {
      throw new EvalException(
          loc,
          String.format(
              "cannot add an item of type '%s' to a depset of '%s'", itemType, depsetType));
    }
    return resultType;
  }

  /**
   * Throws EvalException if a given value is mutable.
   */
  private static void checkImmutable(Object o, Location loc) throws EvalException {
    if (!EvalUtils.isImmutable(o)) {
      throw new EvalException(loc, "depsets cannot contain mutable items");
    }
  }

  private void checkHasContentType(Class<?> type) {
    // Empty sets should be SkylarkType.TOP anyway.
    if (!set.isEmpty()) {
      Preconditions.checkArgument(
          contentType.canBeCastTo(type),
          "Expected a depset of '%s' but got a depset of '%s'",
          EvalUtils.getDataTypeNameFromClass(type), contentType);
    }
  }

  /**
   * Returns the embedded {@link NestedSet}, while asserting that its elements all have the given
   * type.
   *
   * <p>If you do not specifically need the {@code NestedSet} and you are going to flatten it
   * anyway, prefer {@link #toCollection} to make your intent clear.
   *
   * @param type a {@link Class} representing the expected type of the contents
   * @return the {@code NestedSet}, with the appropriate generic type
   * @throws IllegalArgumentException if the type does not accurately describe all elements
   */
  // The precondition ensures generic type safety.
  @SuppressWarnings("unchecked")
  public <T> NestedSet<T> getSet(Class<T> type) {
    checkHasContentType(type);
    return (NestedSet<T>) set;
  }

  /**
   * Returns the contents of the set as a {@link Collection}.
   */
  public Collection<Object> toCollection() {
    return ImmutableList.copyOf(set.toCollection());
  }

  /**
   * Returns the contents of the set as a {@link Collection}, asserting that the set type is
   * compatible with {@code T}.
   *
   * @param type a {@link Class} representing the expected type of the contents
   * @throws IllegalArgumentException if the type does not accurately describe all elements
   */
  // The precondition ensures generic type safety.
  @SuppressWarnings("unchecked")
  public <T> Collection<T> toCollection(Class<T> type) {
    checkHasContentType(type);
    return (Collection<T>) toCollection();
  }

  public boolean isEmpty() {
    return set.isEmpty();
  }

  public SkylarkType getContentType() {
    return contentType;
  }

  @Override
  public String toString() {
    return Printer.repr(this);
  }

  public Order getOrder() {
    return set.getOrder();
  }

  @Override
  public boolean isImmutable() {
    return true;
  }

  @Override
  public void repr(SkylarkPrinter printer) {
    printer.append("depset(");
    printer.printList(set, "[", ", ", "]", null);
    Order order = getOrder();
    if (order != Order.STABLE_ORDER) {
      printer.append(", order = ");
      printer.repr(order.getSkylarkName());
    }
    printer.append(")");
  }

  @Override
  public final boolean containsKey(Object key, Location loc) throws EvalException {
    return (set.toList().contains(key));
  }

  @SkylarkCallable(
      name = "union",
      doc =
          "<i>(Deprecated)</i> Returns a new <a href=\"depset.html\">depset</a> that is the merge "
              + "of the given depset and <code>new_elements</code>. Use the "
              + "<code>transitive</code> constructor argument instead.",
      parameters = {
          @Param(name = "new_elements", type = Object.class, doc = "The elements to be added.")
      },
      useLocation = true,
      useEnvironment = true
  )
  public SkylarkNestedSet union(Object newElements, Location loc, Environment env)
      throws EvalException {
    if (env.getSemantics().incompatibleDepsetUnion()) {
      throw new EvalException(
          loc,
          "depset method `.union` has been removed. See "
              + "https://docs.bazel.build/versions/master/skylark/depsets.html for "
              + "recommendations. Use --incompatible_depset_union=false "
              + "to temporarily disable this check.");
    }
    // newElements' type is Object because of the polymorphism on unioning two
    // SkylarkNestedSets versus a set and another kind of iterable.
    // Can't use EvalUtils#toIterable since that would discard this information.
    return SkylarkNestedSet.of(this, newElements, loc);
  }

  @SkylarkCallable(
      name = "to_list",
      doc =
          "Returns a list of the elements, without duplicates, in the depset's traversal order. "
              + "Note that order is unspecified (but deterministic) for elements that were added "
              + "more than once to the depset. Order is also unspecified for <code>\"default\""
              + "</code>-ordered depsets, and for elements of child depsets whose order differs "
              + "from that of the parent depset. The list is a copy; modifying it has no effect "
              + "on the depset and vice versa.",
      useEnvironment = true
  )
  public MutableList<Object> toList(Environment env) {
    return MutableList.copyOf(env, this.toCollection());
  }

  /**
   * Create a {@link Builder} with specified order.
   *
   * <p>The {@code Builder} will use {@code location} to report errors.
   */
  public static Builder builder(Order order, Location location) {
    return new Builder(order, location);
  }

  /**
   * Builder for {@link SkylarkNestedSet}.
   *
   * <p>Use this to construct typesafe Skylark nested sets (depsets).
   * Encapsulates content type checking logic.
   */
  public static final class Builder {

    private final Order order;
    private final NestedSetBuilder<Object> builder;
    /** Location for error messages */
    private final Location location;
    private SkylarkType contentType = SkylarkType.TOP;
    private SkylarkType lastInsertedType = null;

    private Builder(Order order, Location location) {
      this.order = order;
      this.location = location;
      this.builder = new NestedSetBuilder<>(order);
    }

    /**
     * Add a direct element, checking its type to be compatible to already added
     * elements and transitive sets.
     */
    public Builder addDirect(Object direct) throws EvalException {
      SkylarkType elemType = SkylarkType.of(direct.getClass());
      contentType = getTypeAfterInsert(contentType, elemType, lastInsertedType, location);
      lastInsertedType = elemType;
      builder.add(direct);
      return this;
    }

    /**
     * Add a transitive set, checking its content type to be compatible to already added
     * elements and transitive sets.
     */
    public Builder addTransitive(SkylarkNestedSet transitive) throws EvalException {
      if (transitive.isEmpty()) {
        return this;
      }

      contentType = getTypeAfterInsert(
          contentType, transitive.getContentType(), lastInsertedType, this.location);
      lastInsertedType = transitive.getContentType();

      if (!order.isCompatible(transitive.getOrder())) {
        throw new EvalException(location,
            String.format("Order '%s' is incompatible with order '%s'",
                          order.getSkylarkName(), transitive.getOrder().getSkylarkName()));
      }
      builder.addTransitive(transitive.getSet(Object.class));
      return this;
    }

    public SkylarkNestedSet build() {
      return new SkylarkNestedSet(contentType, builder.build(), null, null);
    }
  }
}
