/*
 * Copyright 2007 Google Inc.
 *
 * 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 java.util;

import static javaemul.internal.InternalPreconditions.checkCriticalPositionIndexes;
import static javaemul.internal.InternalPreconditions.checkElement;
import static javaemul.internal.InternalPreconditions.checkElementIndex;
import static javaemul.internal.InternalPreconditions.checkNotNull;
import static javaemul.internal.InternalPreconditions.checkPositionIndex;
import static javaemul.internal.InternalPreconditions.checkState;

import jsinterop.annotations.JsNonNull;

/**
 * Skeletal implementation of the List interface. <a
 * href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/AbstractList.html">[Sun
 * docs]</a>
 *
 * @param <E> the element type.
 */
public abstract class AbstractList<E> extends AbstractCollection<E> implements
    List<E> {

  private class IteratorImpl implements Iterator<E> {
    /*
     * i is the index of the item that will be returned on the next call to
     * next() last is the index of the item that was returned on the previous
     * call to next() or previous (for ListIterator), -1 if no such item exists.
     */

    int i = 0, last = -1;

    @Override
    public boolean hasNext() {
      return i < AbstractList.this.size();
    }

    @Override
    public E next() {
      checkElement(hasNext());

      return AbstractList.this.get(last = i++);
    }

    @Override
    public void remove() {
      checkState(last != -1);

      AbstractList.this.remove(last);
      i = last;
      last = -1;
    }
  }

  /**
   * Implementation of <code>ListIterator</code> for abstract lists.
   */
  private final class ListIteratorImpl extends IteratorImpl implements
      ListIterator<E> {
    /*
     * i is the index of the item that will be returned on the next call to
     * next() last is the index of the item that was returned on the previous
     * call to next() or previous (for ListIterator), -1 if no such item exists.
     */

    private ListIteratorImpl() {
      // Nothing to do
    }

    private ListIteratorImpl(int start) {
      checkPositionIndex(start, AbstractList.this.size());

      i = start;
    }

    @Override
    public void add(E o) {
      AbstractList.this.add(i, o);
      i++;
      last = -1;
    }

    @Override
    public boolean hasPrevious() {
      return i > 0;
    }

    @Override
    public int nextIndex() {
      return i;
    }

    @Override
    public E previous() {
      checkElement(hasPrevious());

      return AbstractList.this.get(last = --i);
    }

    @Override
    public int previousIndex() {
      return i - 1;
    }

    @Override
    public void set(E o) {
      checkState(last != -1);

      AbstractList.this.set(last, o);
    }
  }

  private static class SubList<E> extends AbstractList<E> {
    private final List<E> wrapped;
    private final int fromIndex;
    private int size;

    public SubList(List<E> wrapped, int fromIndex, int toIndex) {
      checkCriticalPositionIndexes(fromIndex, toIndex, wrapped.size());

      this.wrapped = wrapped;
      this.fromIndex = fromIndex;
      this.size = toIndex - fromIndex;
    }

    @Override
    public void add(int index, E element) {
      checkPositionIndex(index, size);

      wrapped.add(fromIndex + index, element);
      size++;
    }

    @Override
    public E get(int index) {
      checkElementIndex(index, size);

      return wrapped.get(fromIndex + index);
    }

    @Override
    public E remove(int index) {
      checkElementIndex(index, size);

      E result = wrapped.remove(fromIndex + index);
      size--;
      return result;
    }

    @Override
    public E set(int index, E element) {
      checkElementIndex(index, size);

      return wrapped.set(fromIndex + index, element);
    }

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

  protected transient int modCount;

  protected AbstractList() {
  }

  @Override
  public boolean add(E obj) {
    add(size(), obj);
    return true;
  }

  @Override
  public void add(int index, E element) {
    throw new UnsupportedOperationException("Add not supported on this list");
  }

  @Override
  public boolean addAll(int index, Collection<? extends E> c) {
    checkNotNull(c);

    boolean changed = false;
    for (E e : c) {
      add(index++, e);
      changed = true;
    }
    return changed;
  }

  @Override
  public void clear() {
    removeRange(0, size());
  }

  @Override
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }

    if (!(o instanceof List)) {
      return false;
    }

    List<?> other = (List<?>) o;
    if (size() != other.size()) {
      return false;
    }

    Iterator<?> iterOther = other.iterator();
    for (E elem : this) {
      Object elemOther = iterOther.next();
      if (!Objects.equals(elem, elemOther)) {
        return false;
      }
    }

    return true;
  }

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

  @Override
  public int indexOf(Object toFind) {
    for (int i = 0, n = size(); i < n; ++i) {
      if (Objects.equals(toFind, get(i))) {
        return i;
      }
    }
    return -1;
  }

  @Override
  public Iterator<E> iterator() {
    return new IteratorImpl();
  }

  @Override
  public int lastIndexOf(Object toFind) {
    for (int i = size() - 1; i > -1; --i) {
      if (Objects.equals(toFind, get(i))) {
        return i;
      }
    }
    return -1;
  }

  @Override
  public ListIterator<E> listIterator() {
    return listIterator(0);
  }

  @Override
  public ListIterator<E> listIterator(int from) {
    return new ListIteratorImpl(from);
  }

  @Override
  public E remove(int index) {
    throw new UnsupportedOperationException("Remove not supported on this list");
  }

  @Override
  public E set(int index, E o) {
    throw new UnsupportedOperationException("Set not supported on this list");
  }

  @Override
  @JsNonNull
  public List<E> subList(int fromIndex, int toIndex) {
    return new SubList<E>(this, fromIndex, toIndex);
  }

  protected void removeRange(int fromIndex, int endIndex) {
    ListIterator<E> iter = listIterator(fromIndex);
    for (int i = fromIndex; i < endIndex; ++i) {
      iter.next();
      iter.remove();
    }
  }
}
