/* MyListIterator.java */

import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * A ListIterator that will iterate over any given List.
 * 
 * @see java.util.ListIterator
 * @see java.util.List
 * 
 * @author Zach Tomaszewski
 * @version 01 Feb 2005
 */
public class MyListIterator implements ListIterator {

  private List list;     // the list this iterator traverses
  private int currIndex; //the index of the element returned by next
                         //call to next() 
  private int lastReturned;  //the index of the last returned element
                             //(either from next() or previous());
  private static final int INVALID = -1;  //used for lastReturned


  /**
   * Creates a new iterator for the given List
   *
   * @param list  The list this iterator will traverse
   */
  public MyListIterator(List list) {
    this.list = list;
    this.currIndex = 0;
    this.lastReturned = INVALID;
  }
 

  /* ListIterator METHODS -- see java.util.ListIterator for docs */

  public void add(Object o) {
    list.add(currIndex, o);
    currIndex++;  //results of next() are affected by adding
    lastReturned = INVALID; 
  }

  public boolean hasNext() {
    return (currIndex < list.size()); 
  }

  public boolean hasPrevious() {
    return (currIndex > 0);
  }

  public Object next() throws NoSuchElementException {
    if (this.hasNext()) {
      lastReturned = currIndex;  //now valid again
      return list.get(currIndex++); //get currIndex, then increment
    }else {
      throw new NoSuchElementException(); 
    }
  }

  public int nextIndex() {
    return currIndex; 
  }

  public Object previous() throws NoSuchElementException {
    if (this.hasPrevious()) {
      currIndex--;
      lastReturned = currIndex; //now valid again
      return list.get(currIndex);
    }else {
      throw new NoSuchElementException(); 
    }
  }

  public int previousIndex() {
    return currIndex - 1;
  }

  public void remove() {
    if (lastReturned == INVALID) {
      //next() or previous() not last method called, so remove undefined
      throw new IllegalStateException();
    }else {
      list.remove(lastReturned);
      if (lastReturned < currIndex) {
        //list just shrunk since we removed a previous item in the list
        //so need to move currIndex back so we point at same item 
        //as before remove
        currIndex--;
      }
      lastReturned = INVALID;
    }
  }

  public void set(Object o) {
    if (lastReturned == INVALID) {
      //next() or previous() not last method called, so remove undefined
      throw new IllegalStateException();
    }else {
      list.set(lastReturned, o);
    }
  }


  /**
   * Creates a short list and briefly tests a MyListIterator
   * by traversing the list and printing its contents to the screen.
   */
  public static void main(String[] args) {
    
    List names = new DLList();
    names.add(0, new String("Doug"));
    names.add(0, new String("Andrew"));
    names.add(0, new String("Sarah"));
    names.add(0, new String("Michael"));
    names.add(0, new String("Frank"));

    MyListIterator iter = new MyListIterator(names);

    iter.add("Janet"); // adds Janet to beginning of list
    iter.previous(); // moves iterator back one location

    System.out.print("Expected list: ");
    System.out.println("Janet, Frank, Michael, Sarah, Andrew, Doug.");

    while (iter.hasNext()) {
      System.out.print("index: " + iter.nextIndex());
      System.out.println(" value: " + iter.next());
    }
  }

}//end class

