// CHECKSTYLE_OFF: Copyrighted to ASF
/*
 * Copyright 1999-2004 The Apache Software Foundation
 *
 * 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.
 */
// CHECKSTYLE_ON
package com.google.gwt.emultest.java.util;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * Tests base {@link java.util.List} methods and contracts.
 *
 * <p>To use, simply extend this class, and implement the {@link #makeList} method.
 *
 * <p>If your {@link List} fails one of these tests by design, you may still use this base set of
 * cases. Simply override the test case (method) your {@link List} fails.
 */
@SuppressWarnings({"unchecked", "rawtypes"})
abstract class TestList extends TestCollection {

  /**
   * Return a new, empty {@link List} to be used for testing.
   *
   * @return an empty list for testing.
   */
  protected abstract List makeEmptyList();

  /**
   * Return a new, full {@link List} to be used for testing.
   *
   * @return a full list for testing
   */
  protected List makeFullList() {
    // only works if list supports optional "addAll(Collection)"
    List list = makeEmptyList();
    list.addAll(Arrays.asList(getFullElements()));
    return list;
  }

  /**
   * Returns {@link makeEmptyList()}.
   *
   * @return an empty list to be used for testing
   */
  @Override
  protected final Collection makeCollection() {
    return makeEmptyList();
  }

  /**
   * Returns {@link makeFullList()}.
   *
   * @return a full list to be used for testing
   */
  @Override
  protected final Collection makeFullCollection() {
    return makeFullList();
  }

  /**
   * Whether or not we are testing an iterator that can be empty. Default is true.
   *
   * @return true if Iterators can be empty
   */
  public boolean supportsEmptyIterator() {
    return true;
  }

  /**
   * Whether or not we are testing an list that allows element set. Default is true.
   *
   * @return true if Lists support element set
   */
  public boolean isSetSupported() {
    return true;
  }

  /**
   * Returns the {@link collection} field cast to a {@link List}.
   *
   * @return the collection field as a List
   */
  protected List getList() {
    return (List) collection;
  }

  /**
   * Returns the {@link confirmed} field cast to a {@link List}.
   *
   * @return the confirmed field as a List
   */
  protected List getConfirmedList() {
    return (List) confirmed;
  }

  public class TestListIterator extends AbstractTestListIterator {

    @Override
    public Object addSetValue() {
      return TestList.this.getOtherElements()[0];
    }

    @Override
    public boolean supportsRemove() {
      return TestList.this.isRemoveSupported();
    }

    @Override
    public boolean supportsAdd() {
      return TestList.this.isAddSupported();
    }

    @Override
    public boolean supportsSet() {
      return TestList.this.isSetSupported();
    }

    @Override
    public ListIterator makeEmptyListIterator() {
      resetEmpty();
      return ((List) TestList.this.collection).listIterator();
    }

    @Override
    public ListIterator makeFullListIterator() {
      resetFull();
      return ((List) TestList.this.collection).listIterator();
    }

    @Override
    public Object makeObject() {
      return ((List) TestList.this.collection).listIterator();
    }
  }

  /** Tests the read-only bits of {@link List#listIterator()}. */
  public void testListListIterator() {
    resetFull();
    forwardTest(getList().listIterator(), 0);
    backwardTest(getList().listIterator(), 0);
  }

  /** Tests the read-only bits of {@link List#listIterator(int)}. */
  public void testListListIteratorByIndex() {
    resetFull();
    try {
      getList().listIterator(-1);
    } catch (IndexOutOfBoundsException ex) {
    }
    resetFull();
    try {
      getList().listIterator(getList().size() + 1);
    } catch (IndexOutOfBoundsException ex) {
    }
    resetFull();
    for (int i = 0; i <= confirmed.size(); i++) {
      forwardTest(getList().listIterator(i), i);
      backwardTest(getList().listIterator(i), i);
    }
    resetFull();
    for (int i = 0; i <= confirmed.size(); i++) {
      backwardTest(getList().listIterator(i), i);
    }
  }

  // -----------------------------------------------------------------------
  /** Tests remove on list iterator is correct. */
  public void testListListIteratorPreviousRemoveNext() {
    if (!isRemoveSupported()) {
      return;
    }
    resetFull();
    if (collection.size() < 4) {
      return;
    }
    ListIterator it = getList().listIterator();
    Object zero = it.next();
    Object one = it.next();
    Object two = it.next();
    Object two2 = it.previous();
    Object one2 = it.previous();
    assertEquals(one, one2);
    assertEquals(two, two2);
    assertEquals(zero, getList().get(0));
    assertEquals(one, getList().get(1));
    assertEquals(two, getList().get(2));

    it.remove(); // removed element at index 1 (one)
    assertEquals(zero, getList().get(0));
    assertEquals(two, getList().get(1));
    Object two3 = it.next(); // do next after remove
    assertEquals(two, two3);
    assertEquals(collection.size() > 2, it.hasNext());
    assertTrue(it.hasPrevious());
  }

  /** Tests remove on list iterator is correct. */
  public void testListListIteratorPreviousRemovePrevious() {
    if (!isRemoveSupported()) {
      return;
    }
    resetFull();
    if (collection.size() < 4) {
      return;
    }
    ListIterator it = getList().listIterator();
    Object zero = it.next();
    Object one = it.next();
    Object two = it.next();
    Object two2 = it.previous();
    Object one2 = it.previous();
    assertEquals(one, one2);
    assertEquals(two, two2);
    assertEquals(zero, getList().get(0));
    assertEquals(one, getList().get(1));
    assertEquals(two, getList().get(2));

    it.remove(); // removed element at index 1 (one)
    assertEquals(zero, getList().get(0));
    assertEquals(two, getList().get(1));
    Object zero3 = it.previous(); // do previous after remove
    assertEquals(zero, zero3);
    assertEquals(false, it.hasPrevious());
    assertEquals(collection.size() > 2, it.hasNext());
  }

  /** Tests remove on list iterator is correct. */
  public void testListListIteratorNextRemoveNext() {
    if (!isRemoveSupported()) {
      return;
    }
    resetFull();
    if (collection.size() < 4) {
      return;
    }
    ListIterator it = getList().listIterator();
    Object zero = it.next();
    Object one = it.next();
    Object two = it.next();
    assertEquals(zero, getList().get(0));
    assertEquals(one, getList().get(1));
    assertEquals(two, getList().get(2));
    Object three = getList().get(3);

    it.remove(); // removed element at index 2 (two)
    assertEquals(zero, getList().get(0));
    assertEquals(one, getList().get(1));
    Object three2 = it.next(); // do next after remove
    assertEquals(three, three2);
    assertEquals(collection.size() > 3, it.hasNext());
    assertEquals(true, it.hasPrevious());
  }

  /** Tests remove on list iterator is correct. */
  public void testListListIteratorNextRemovePrevious() {
    if (!isRemoveSupported()) {
      return;
    }
    resetFull();
    if (collection.size() < 4) {
      return;
    }
    ListIterator it = getList().listIterator();
    Object zero = it.next();
    Object one = it.next();
    Object two = it.next();
    assertEquals(zero, getList().get(0));
    assertEquals(one, getList().get(1));
    assertEquals(two, getList().get(2));

    it.remove(); // removed element at index 2 (two)
    assertEquals(zero, getList().get(0));
    assertEquals(one, getList().get(1));
    Object one2 = it.previous(); // do previous after remove
    assertEquals(one, one2);
    assertEquals(true, it.hasNext());
    assertEquals(true, it.hasPrevious());
  }

  // -----------------------------------------------------------------------
  /**
   * Traverses to the end of the given iterator.
   *
   * @param iter the iterator to traverse
   * @param i the starting index
   */
  private void forwardTest(ListIterator iter, int i) {
    List list = getList();
    int max = getFullElements().length;

    while (i < max) {
      assertTrue("Iterator should have next", iter.hasNext());
      assertEquals("Iterator.nextIndex should work", iter.nextIndex(), i);
      assertEquals("Iterator.previousIndex should work", iter.previousIndex(), i - 1);
      Object o = iter.next();
      assertEquals("Iterator returned correct element f", list.get(i), o);
      i++;
    }

    assertTrue("Iterator shouldn't have next", !iter.hasNext());
    assertEquals("nextIndex should be size", iter.nextIndex(), max);
    assertEquals("previousIndex should be size - 1", iter.previousIndex(), max - 1);

    try {
      iter.next();
      fail("Exhausted iterator should raise NoSuchElement");
    } catch (NoSuchElementException e) {
      // expected
    }
  }

  /**
   * Traverses to the beginning of the given iterator.
   *
   * @param iter the iterator to traverse
   * @param i the starting index
   */
  private void backwardTest(ListIterator iter, int i) {
    List list = getList();

    while (i > 0) {
      assertTrue("Iterator should have previous, i:" + i, iter.hasPrevious());
      assertEquals("Iterator.nextIndex should work, i:" + i, iter.nextIndex(), i);
      assertEquals("Iterator.previousIndex should work, i:" + i, iter.previousIndex(), i - 1);
      Object o = iter.previous();
      assertEquals("Iterator returned correct element b", list.get(i - 1), o);
      i--;
    }

    assertTrue("Iterator shouldn't have previous", !iter.hasPrevious());
    int nextIndex = iter.nextIndex();
    assertEquals("nextIndex should be 0, actual value: " + nextIndex, 0, nextIndex);
    int prevIndex = iter.previousIndex();
    assertEquals("previousIndex should be -1, actual value: " + prevIndex, -1, prevIndex);

    try {
      iter.previous();
      fail("Exhausted iterator should raise NoSuchElement");
    } catch (NoSuchElementException e) {
      // expected
    }
  }

  /** Tests the {@link ListIterator#add(Object)} method of the list iterator. */
  public void testListIteratorAdd() {
    if (!isAddSupported()) {
      return;
    }

    resetEmpty();
    List list1 = getList();
    List list2 = getConfirmedList();

    Object[] elements = getFullElements();
    ListIterator iter1 = list1.listIterator();
    ListIterator iter2 = list2.listIterator();

    for (int i = 0; i < elements.length; i++) {
      iter1.add(elements[i]);
      iter2.add(elements[i]);
      verify();
    }

    resetFull();
    iter1 = getList().listIterator();
    iter2 = getConfirmedList().listIterator();
    for (int i = 0; i < elements.length; i++) {
      iter1.next();
      iter2.next();
      iter1.add(elements[i]);
      iter2.add(elements[i]);
      verify();
    }
  }

  /** Tests the {@link ListIterator#set(Object)} method of the list iterator. */
  public void testListIteratorSet() {
    if (!isSetSupported()) {
      return;
    }

    Object[] elements = getFullElements();

    resetFull();
    ListIterator iter1 = getList().listIterator();
    ListIterator iter2 = getConfirmedList().listIterator();
    for (int i = 0; i < elements.length; i++) {
      iter1.next();
      iter2.next();
      iter1.set(elements[i]);
      iter2.set(elements[i]);
      verify();
    }
  }

  /** Tests {@link List#add(int,Object)}. */
  public void testListAddByIndex() {
    if (!isAddSupported()) {
      return;
    }

    Object element = getOtherElements()[0];
    int max = getFullElements().length;

    for (int i = 0; i <= max; i++) {
      resetFull();
      ((List) collection).add(i, element);
      ((List) confirmed).add(i, element);
      verify();
    }
  }

  /** Tests {@link List#equals(Object)}. */
  public void testListEquals() {
    resetEmpty();
    List list = getList();
    assertTrue("Empty lists should be equal", list.equals(confirmed));
    verify();
    assertTrue("Empty list should equal self", list.equals(list));
    verify();

    List list2 = Arrays.asList(getFullElements());
    assertTrue("Empty list shouldn't equal full", !list.equals(list2));
    verify();

    list2 = Arrays.asList(getOtherElements());
    assertTrue("Empty list shouldn't equal other", !list.equals(list2));
    verify();

    resetFull();
    list = getList();
    assertTrue("Full lists should be equal", list.equals(confirmed));
    verify();
    assertTrue("Full list should equal self", list.equals(list));
    verify();

    list2 = makeEmptyList();
    assertTrue("Full list shouldn't equal empty", !list.equals(list2));
    verify();

    list2 = Arrays.asList(getOtherElements());
    assertTrue("Full list shouldn't equal other", !list.equals(list2));
    verify();

    list2 = Arrays.asList(getFullElements());
    Collections.reverse(list2);
    assertTrue(
        "Full list shouldn't equal full list with same elements" + " but different order",
        !list.equals(list2));
    verify();

    assertTrue("List shouldn't equal String", !list.equals(""));
    verify();

    final List listForC = Arrays.asList(getFullElements());
    Collection c =
        new AbstractCollection() {
          @Override
          public int size() {
            return listForC.size();
          }

          @Override
          public Iterator iterator() {
            return listForC.iterator();
          }
        };

    assertTrue(
        "List shouldn't equal nonlist with same elements " + " in same order", !list.equals(c));
    verify();
  }

  /** Tests {@link List#hashCode()}. */
  public void testListHashCode() {
    resetEmpty();
    int hash1 = collection.hashCode();
    int hash2 = confirmed.hashCode();
    assertEquals("Empty lists should have equal hashCodes", hash1, hash2);
    verify();

    resetFull();
    hash1 = collection.hashCode();
    hash2 = confirmed.hashCode();
    assertEquals("Full lists should have equal hashCodes", hash1, hash2);
    verify();
  }

  /** Tests {@link List#get(int)}. */
  public void testListGetByIndex() {
    resetFull();
    List list = getList();
    Object[] elements = getFullElements();
    for (int i = 0; i < elements.length; i++) {
      assertEquals("List should contain correct elements", elements[i], list.get(i));
      verify();
    }
  }

  /** Tests {@link List#indexOf()}. */
  public void testListIndexOf() {
    resetFull();
    List list1 = getList();
    List list2 = getConfirmedList();

    Iterator iterator = list2.iterator();
    while (iterator.hasNext()) {
      Object element = iterator.next();
      assertEquals(
          "indexOf should return correct result", list1.indexOf(element), list2.indexOf(element));
      verify();
    }

    Object[] other = getOtherElements();
    for (int i = 0; i < other.length; i++) {
      assertEquals("indexOf should return -1 for nonexistent element", -1, list1.indexOf(other[i]));
      verify();
    }
  }

  /** Tests {@link List#lastIndexOf()}. */
  public void testListLastIndexOf() {
    resetFull();
    List list1 = getList();
    List list2 = getConfirmedList();

    Iterator iterator = list2.iterator();
    while (iterator.hasNext()) {
      Object element = iterator.next();
      assertEquals(
          "lastIndexOf should return correct result",
          list1.lastIndexOf(element),
          list2.lastIndexOf(element));
      verify();
    }

    Object[] other = getOtherElements();
    for (int i = 0; i < other.length; i++) {
      assertEquals(
          "lastIndexOf should return -1 for nonexistent " + "element",
          -1,
          list1.lastIndexOf(other[i]));
      verify();
    }
  }

  /** Tests {@link List#remove(int)}. */
  public void testListRemoveByIndex() {
    if (!isRemoveSupported()) {
      return;
    }

    int max = getFullElements().length;
    for (int i = 0; i < max; i++) {
      resetFull();
      Object o1 = ((List) collection).remove(i);
      Object o2 = ((List) confirmed).remove(i);
      assertEquals("remove should return correct element", o1, o2);
      verify();
    }
  }

  /** Returns an empty {@link ArrayList}. */
  @Override
  protected Collection makeConfirmedCollection() {
    ArrayList list = new ArrayList();
    return list;
  }

  /** Returns a full {@link ArrayList}. */
  @Override
  protected Collection makeConfirmedFullCollection() {
    ArrayList list = new ArrayList();
    list.addAll(Arrays.asList(getFullElements()));
    return list;
  }

  /** Verifies that the test list implementation matches the confirmed list implementation. */
  @Override
  protected void verify() {
    super.verify();

    List list1 = getList();
    List list2 = getConfirmedList();

    assertEquals("List should equal confirmed", list1, list2);
    assertEquals("Confirmed should equal list", list2, list1);

    assertEquals("Hash codes should be equal", list1.hashCode(), list2.hashCode());

    int i = 0;
    Iterator iterator1 = list1.iterator();
    Iterator iterator2 = list2.iterator();
    Object[] array = list1.toArray();
    while (iterator2.hasNext()) {
      assertTrue("List iterator should have next", iterator1.hasNext());
      Object o1 = iterator1.next();
      Object o2 = iterator2.next();
      assertEquals("Iterator elements should be equal", o1, o2);
      o2 = list1.get(i);
      assertEquals("get should return correct element", o1, o2);
      o2 = array[i];
      assertEquals("toArray should have correct element", o1, o2);
      i++;
    }
  }
}
