// 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.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.events.Location;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;

/** A StarlarkList is a mutable finite sequence of values. */
@SkylarkModule(
    name = "list",
    category = SkylarkModuleCategory.BUILTIN,
    doc =
        "The built-in list type. Example list expressions:<br>"
            + "<pre class=language-python>x = [1, 2, 3]</pre>"
            + "Accessing elements is possible using indexing (starts from <code>0</code>):<br>"
            + "<pre class=language-python>e = x[1]   # e == 2</pre>"
            + "Lists support the <code>+</code> operator to concatenate two lists. Example:<br>"
            + "<pre class=language-python>x = [1, 2] + [3, 4]   # x == [1, 2, 3, 4]\n"
            + "x = [\"a\", \"b\"]\n"
            + "x += [\"c\"]            # x == [\"a\", \"b\", \"c\"]</pre>"
            + "Similar to strings, lists support slice operations:"
            + "<pre class=language-python>['a', 'b', 'c', 'd'][1:3]   # ['b', 'c']\n"
            + "['a', 'b', 'c', 'd'][::2]  # ['a', 'c']\n"
            + "['a', 'b', 'c', 'd'][3:0:-1]  # ['d', 'c', 'b']</pre>"
            + "Lists are mutable, as in Python.")
public final class StarlarkList<E> extends Sequence<E> implements StarlarkMutable {

  private final ArrayList<E> contents;

  /** Final except for {@link #unsafeShallowFreeze}; must not be modified any other way. */
  private Mutability mutability;

  private StarlarkList(ArrayList<E> rawContents, @Nullable Mutability mutability) {
    this.contents = Preconditions.checkNotNull(rawContents);
    this.mutability = mutability == null ? Mutability.IMMUTABLE : mutability;
  }

  /**
   * Creates an instance, taking ownership of the supplied {@link ArrayList}. This is exposed for
   * performance reasons. May be used when the calling code will not modify the supplied list after
   * calling (honor system).
   */
  static <T> StarlarkList<T> wrapUnsafe(@Nullable StarlarkThread thread, ArrayList<T> rawContents) {
    return wrapUnsafe(thread == null ? null : thread.mutability(), rawContents);
  }

  /**
   * Create an instance, taking ownership of the supplied {@link ArrayList}. This is exposed for
   * performance reasons. May be used when the calling code will not modify the supplied list after
   * calling (honor system).
   */
  static <T> StarlarkList<T> wrapUnsafe(@Nullable Mutability mutability, ArrayList<T> rawContents) {
    return new StarlarkList<>(rawContents, mutability);
  }

  @Override
  public boolean isImmutable() {
    return mutability().isFrozen();
  }

  @Override
  public boolean isHashable() {
    return false; // even a frozen list is unhashable in Starlark
  }

  /**
   * A shared instance for the empty list with immutable mutability.
   *
   * <p>Other immutable empty list objects can exist, e.g. lists that were once mutable but whose
   * environments were then frozen. This instance is for empty lists that were always frozen from
   * the beginning.
   */
  private static final StarlarkList<?> EMPTY =
      StarlarkList.copyOf(Mutability.IMMUTABLE, ImmutableList.of());

  /** Returns an empty frozen list, cast to have an arbitrary content type. */
  @SuppressWarnings("unchecked")
  public static <T> StarlarkList<T> empty() {
    return (StarlarkList<T>) EMPTY;
  }

  /**
   * Returns a {@code StarlarkList} whose items are given by an iterable and which has the given
   * {@link Mutability}. If {@code mutability} is null, the list is immutable.
   */
  public static <T> StarlarkList<T> copyOf(
      @Nullable Mutability mutability, Iterable<? extends T> contents) {
    return new StarlarkList<>(Lists.newArrayList(contents), mutability);
  }

  /**
   * Returns a {@code StarlarkList} whose items are given by an iterable and which has the {@link
   * Mutability} belonging to the given {@link StarlarkThread}. If {@code thread} is null, the list
   * is immutable.
   */
  public static <T> StarlarkList<T> copyOf(
      @Nullable StarlarkThread thread, Iterable<? extends T> contents) {
    return StarlarkList.copyOf(thread == null ? null : thread.mutability(), contents);
  }

  /**
   * Returns a {@code StarlarkList} with the given items and the {@link Mutability} of the given
   * {@link StarlarkThread}. If {@code thread} is null, the list is immutable.
   */
  public static <T> StarlarkList<T> of(@Nullable StarlarkThread thread, T... contents) {
    // Safe since we're taking a copy of the input.
    return StarlarkList.wrapUnsafe(
        thread == null ? null : thread.mutability(), Lists.newArrayList(contents));
  }

  @Override
  public Mutability mutability() {
    return mutability;
  }

  @Override
  public void unsafeShallowFreeze() {
    Mutability.Freezable.checkUnsafeShallowFreezePrecondition(this);
    this.mutability = Mutability.IMMUTABLE;
  }

  @Override
  public ImmutableList<E> getImmutableList() {
    return ImmutableList.copyOf(contents);
  }

  @Override
  protected List<E> getContentsUnsafe() {
    return contents;
  }

  /**
   * Returns a new {@code StarlarkList} that is the concatenation of two {@code StarlarkList}s. The
   * new list will have the given {@link Mutability}.
   */
  public static <T> StarlarkList<T> concat(
      StarlarkList<? extends T> left, StarlarkList<? extends T> right, Mutability mutability) {

    ArrayList<T> newContents = new ArrayList<>(left.size() + right.size());
    addAll(newContents, left.contents);
    addAll(newContents, right.contents);
    return new StarlarkList<>(newContents, mutability);
  }

  /** More efficient {@link List#addAll} replacement when both lists are {@link ArrayList}s. */
  private static <T> void addAll(ArrayList<T> addTo, ArrayList<? extends T> addFrom) {
    // Hot code path, skip iterator.
    for (int i = 0; i < addFrom.size(); i++) {
      addTo.add(addFrom.get(i));
    }
  }

  @Override
  public StarlarkList<E> repeat(int times, Mutability mutability) {
    if (times <= 0) {
      return StarlarkList.wrapUnsafe(mutability, new ArrayList<>());
    }

    ArrayList<E> repeated = new ArrayList<>(this.size() * times);
    for (int i = 0; i < times; i++) {
      repeated.addAll(this);
    }
    return StarlarkList.wrapUnsafe(mutability, repeated);
  }

  @Override
  public StarlarkList<E> getSlice(
      Object start, Object end, Object step, Location loc, Mutability mutability)
      throws EvalException {
    List<Integer> sliceIndices = EvalUtils.getSliceIndices(start, end, step, this.size(), loc);
    ArrayList<E> list = new ArrayList<>(sliceIndices.size());
    // foreach is not used to avoid iterator overhead
    for (int i = 0; i < sliceIndices.size(); ++i) {
      list.add(this.get(sliceIndices.get(i)));
    }
    return StarlarkList.wrapUnsafe(mutability, list);
  }

  /**
   * Appends an element to the end of the list, after validating that mutation is allowed.
   *
   * @param element the element to add
   * @param loc the location to use for error reporting
   */
  public void add(E element, Location loc) throws EvalException {
    checkMutable(loc);
    contents.add(element);
  }

  /**
   * Inserts an element at a given position to the list.
   *
   * @param index the new element's index
   * @param element the element to add
   * @param loc the location to use for error reporting
   */
  public void add(int index, E element, Location loc) throws EvalException {
    checkMutable(loc);
    contents.add(index, element);
  }

  /**
   * Appends all the elements to the end of the list.
   *
   * @param elements the elements to add
   * @param loc the location to use for error reporting
   */
  public void addAll(Iterable<? extends E> elements, Location loc) throws EvalException {
    checkMutable(loc);
    Iterables.addAll(contents, elements);
  }

  /**
   * Removes the element at a given index. The index must already have been validated to be in
   * range.
   *
   * @param index the index of the element to remove
   * @param loc the location to use for error reporting
   */
  public void remove(int index, Location loc) throws EvalException {
    checkMutable(loc);
    contents.remove(index);
  }

  @SkylarkCallable(
      name = "remove",
      doc =
          "Removes the first item from the list whose value is x. "
              + "It is an error if there is no such item.",
      parameters = {@Param(name = "x", type = Object.class, doc = "The object to remove.")},
      useLocation = true)
  public NoneType removeObject(Object x, Location loc) throws EvalException {
    for (int i = 0; i < size(); i++) {
      if (get(i).equals(x)) {
        remove(i, loc);
        return Starlark.NONE;
      }
    }
    throw new EvalException(loc, Printer.format("item %r not found in list", x));
  }

  /**
   * Sets the position at the given index to contain the given value. The index must already have
   * been validated to be in range.
   *
   * @param index the position to change
   * @param value the new value
   * @param loc the location to use for error reporting
   */
  public void set(int index, E value, Location loc) throws EvalException {
    checkMutable(loc);
    contents.set(index, value);
  }

  @SkylarkCallable(
      name = "append",
      doc = "Adds an item to the end of the list.",
      parameters = {
        @Param(name = "item", type = Object.class, doc = "Item to add at the end.", noneable = true)
      },
      useLocation = true)
  @SuppressWarnings("unchecked") // Cast of Object item to E
  public NoneType append(Object item, Location loc) throws EvalException {
    add((E) item, loc);
    return Starlark.NONE;
  }

  @SkylarkCallable(
      name = "clear",
      doc = "Removes all the elements of the list.",
      useLocation = true)
  public NoneType clearMethod(Location loc) throws EvalException {
    checkMutable(loc);
    contents.clear();
    return Starlark.NONE;
  }

  @SkylarkCallable(
      name = "insert",
      doc = "Inserts an item at a given position.",
      parameters = {
        @Param(name = "index", type = Integer.class, doc = "The index of the given position."),
        @Param(name = "item", type = Object.class, doc = "The item.", noneable = true)
      },
      useLocation = true)
  @SuppressWarnings("unchecked") // Cast of Object item to E
  public NoneType insert(Integer index, Object item, Location loc) throws EvalException {
    add(EvalUtils.clampRangeEndpoint(index, size()), (E) item, loc);
    return Starlark.NONE;
  }

  @SkylarkCallable(
      name = "extend",
      doc = "Adds all items to the end of the list.",
      parameters = {@Param(name = "items", type = Object.class, doc = "Items to add at the end.")},
      useLocation = true,
      useStarlarkThread = true)
  @SuppressWarnings("unchecked")
  public NoneType extend(Object items, Location loc, StarlarkThread thread) throws EvalException {
    addAll((Collection<? extends E>) EvalUtils.toCollection(items, loc, thread), loc);
    return Starlark.NONE;
  }

  @SkylarkCallable(
      name = "index",
      doc =
          "Returns the index in the list of the first item whose value is x. "
              + "It is an error if there is no such item.",
      parameters = {
        @Param(name = "x", type = Object.class, doc = "The object to search."),
        @Param(
            name = "start",
            type = Integer.class,
            defaultValue = "None",
            noneable = true,
            named = true,
            doc = "The start index of the list portion to inspect."),
        @Param(
            name = "end",
            type = Integer.class,
            defaultValue = "None",
            noneable = true,
            named = true,
            doc = "The end index of the list portion to inspect.")
      },
      useLocation = true)
  public Integer index(Object x, Object start, Object end, Location loc) throws EvalException {
    int i = start == Starlark.NONE ? 0 : EvalUtils.clampRangeEndpoint((Integer) start, this.size());
    int j =
        end == Starlark.NONE
            ? this.size()
            : EvalUtils.clampRangeEndpoint((Integer) end, this.size());

    while (i < j) {
      if (this.get(i).equals(x)) {
        return i;
      }
      i++;
    }
    throw new EvalException(loc, Printer.format("item %r not found in list", x));
  }

  @SkylarkCallable(
      name = "pop",
      doc =
          "Removes the item at the given position in the list, and returns it. "
              + "If no <code>index</code> is specified, "
              + "it removes and returns the last item in the list.",
      parameters = {
        @Param(
            name = "i",
            type = Integer.class,
            noneable = true,
            defaultValue = "None",
            doc = "The index of the item.")
      },
      useLocation = true)
  public Object pop(Object i, Location loc) throws EvalException {
    int arg = i == Starlark.NONE ? -1 : (Integer) i;
    int index = EvalUtils.getSequenceIndex(arg, size(), loc);
    Object result = get(index);
    remove(index, loc);
    return result;
  }
}
