// Copyright 2016 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.collect.Iterators;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.Mutability.Freezable;
import com.google.devtools.build.lib.syntax.Mutability.MutabilityException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Base class for data structures that are only mutable using a proper, unfrozen {@link Mutability}.
 */
public abstract class StarlarkMutable implements Freezable, SkylarkValue {

  /**
   * Checks whether this object is currently mutable in the given {@link Environment}, and throws
   * an exception if it is not.
   *
   * @deprecated prefer {@link #checkMutable(Location, Mutability)} instead
   */
  @Deprecated
  protected void checkMutable(Location loc, Environment env) throws EvalException {
    checkMutable(loc, env.mutability());
  }

  /**
   * Checks whether this object is currently mutable using the given {@link Mutability}, and throws
   * an exception if it is not.
   *
   * @throws EvalException if the object is not mutable. This may be because the object (i.e., its
   *     {@code Mutability} was frozen, or because it is temporarily locked from mutation (due to
   *     being iterated over by a loop), or because it is associated with a different {@code
   *     Mutability} than the one given.
   */
  protected void checkMutable(Location loc, Mutability mutability) throws EvalException {
    try {
      Mutability.checkMutable(this, mutability);
    } catch (MutabilityException ex) {
      throw new EvalException(loc, ex);
    }
  }

  @Override
  public boolean isImmutable() {
    // By the Mutability invariants, if we're frozen and our Mutability is not SHALLOW_IMMUTABLE,
    // then all contained values are also deeply frozen. Only tuples use SHALLOW_IMMUTABLE and they
    // override this method anyway, so we can just do a constant-time check here.
    return mutability().isFrozen();
  }

  /**
   * Add a new lock at {@code loc}. No effect if frozen.
   */
  public void lock(Location loc) {
    mutability().lock(this, loc);
  }

  /**
   * Remove the lock at {@code loc}; such a lock must already exist. No effect if frozen.
   */
  public void unlock(Location loc) {
    mutability().unlock(this, loc);
  }

  /**
   * Base class for a {@link StarlarkMutable} that implements a Java Collections Framework
   * interface. All of the interface's accessors should be supported, while its mutating methods
   * must be disallowed.
   *
   * <p>Think of this as similar to {@link Collections#unmodifiableList}, etc., except that it's an
   * extendable class rather than a method.
   *
   * <p>A subclass implements a specific data structure interface, say {@link List}, and refines the
   * return type of {@link #getContentsUnsafe} to be that interface. The subclass implements all of
   * the interface's accessors such that they defer to the result of {@code getContentsUnsafe}.
   * Accessors such as {@link Collection#iterator()} must return unmodifiable views. The subclass
   * implements final versions of all the interface's mutating methods such that they are marked
   * {@code @Deprecated} and throw {@link UnsupportedOperationException}.
   *
   * <p>A concrete subclass may provide alternative mutating methods that take in a {@link
   * Mutability} and validate that the mutation is allowed using {@link #checkMutable}. This
   * validation must occur <em>before</em> the mutation, not after, in order to ensure that a frozen
   * value cannot be mutated. (I.e., the fact that the check throws {@link EvalException} does not
   * excuse us from illegally mutating a frozen value, since {@code EvalException} is not a fatal
   * error.)
   *
   * <p>Subclasses need not overwrite the default methods added to some data structures in Java 8.
   * since these are defined in terms of the non-default methods.
   */
  abstract static class BaseMutableWrapper extends StarlarkMutable {

    /**
     * The underlying contents, to which read access is forwarded. This object must not be modified
     * without first calling {@link #checkMutable}.
     */
    protected abstract Object getContentsUnsafe();

    @Override
    public boolean equals(Object o) {
      return getContentsUnsafe().equals(o);
    }

    @Override
    public int hashCode() {
      return getContentsUnsafe().hashCode();
    }
  }

  /** Base class for a {@link StarlarkMutable} that is also a {@link Collection}. */
  abstract static class MutableCollection<E> extends BaseMutableWrapper implements Collection<E> {

    @Override
    protected abstract Collection<E> getContentsUnsafe();

    // Reading methods of Collection, in alphabetic order.

    @Override
    public boolean contains(@Nullable Object object) {
      return getContentsUnsafe().contains(object);
    }

    @Override
    public boolean containsAll(Collection<?> collection) {
      return getContentsUnsafe().containsAll(collection);
    }

    @Override
    public boolean isEmpty() {
      return getContentsUnsafe().isEmpty();
    }

    @Override
    public Iterator<E> iterator() {
      return Iterators.unmodifiableIterator(getContentsUnsafe().iterator());
    }

    @Override
    public int size() {
      return getContentsUnsafe().size();
    }

    // toArray() and toArray(T[]) return copies, so we don't need an unmodifiable view.
    @Override
    public Object[] toArray() {
      return getContentsUnsafe().toArray();
    }

    @Override
    public <T> T[] toArray(T[] other) {
      return getContentsUnsafe().toArray(other);
    }

    // (Disallowed) writing methods of Collection, in alphabetic order.

    @Deprecated
    @Override
    public final boolean add(E element) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final boolean addAll(Collection<? extends E> collection) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final void clear() {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final boolean remove(Object object) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final boolean removeAll(Collection<?> collection) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final boolean retainAll(Collection<?> collection) {
      throw new UnsupportedOperationException();
    }
  }

  /** Base class for a {@link StarlarkMutable} that is also a {@link List}. */
  abstract static class BaseMutableList<E> extends MutableCollection<E> implements List<E> {

    @Override
    protected abstract List<E> getContentsUnsafe();

    // Reading methods of List, in alphabetic order.

    @Override
    public E get(int i) {
      return getContentsUnsafe().get(i);
    }

    @Override
    public int indexOf(Object element) {
      return getContentsUnsafe().indexOf(element);
    }

    @Override
    public int lastIndexOf(Object element) {
      return getContentsUnsafe().lastIndexOf(element);
    }

    @Override
    public ListIterator<E> listIterator() {
      return Collections.unmodifiableList(getContentsUnsafe()).listIterator();
    }

    @Override
    public ListIterator<E> listIterator(int index) {
      return Collections.unmodifiableList(getContentsUnsafe()).listIterator(index);
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
      return Collections.unmodifiableList(getContentsUnsafe()).subList(fromIndex, toIndex);
    }

    // (Disallowed) writing methods of List, in alphabetic order.

    @Deprecated
    @Override
    public final void add(int index, E element) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final boolean addAll(int index, Collection<? extends E> elements) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final E remove(int index) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final E set(int index, E element) {
      throw new UnsupportedOperationException();
    }
  }

  /** Base class for a {@link StarlarkMutable} that is also a {@link Map}. */
  abstract static class MutableMap<K, V> extends BaseMutableWrapper implements Map<K, V> {

    @Override
    protected abstract Map<K, V> getContentsUnsafe();

    // Reading methods of Map, in alphabetic order.

    @Override
    public boolean containsKey(Object key) {
      return getContentsUnsafe().containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
      return getContentsUnsafe().containsValue(value);
    }

    @Override
    public Set<Map.Entry<K, V>> entrySet() {
      return Collections.unmodifiableMap(getContentsUnsafe()).entrySet();
    }

    @Override
    public V get(Object key) {
      return getContentsUnsafe().get(key);
    }

    @Override
    public boolean isEmpty() {
      return getContentsUnsafe().isEmpty();
    }

    @Override
    public Set<K> keySet() {
      return Collections.unmodifiableMap(getContentsUnsafe()).keySet();
    }

    @Override
    public int size() {
      return getContentsUnsafe().size();
    }

    @Override
    public Collection<V> values() {
      return Collections.unmodifiableMap(getContentsUnsafe()).values();
    }

    // (Disallowed) writing methods of Map, in alphabetic order.

    @Deprecated
    @Override
    public final void clear() {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final V put(K key, V value) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final void putAll(Map<? extends K, ? extends V> map) {
      throw new UnsupportedOperationException();
    }

    @Deprecated
    @Override
    public final V remove(Object key) {
      throw new UnsupportedOperationException();
    }
  }
}
