import java.util.AbstractSequentialList;
import java.util.ListIterator;
import java.util.NoSuchElementException;

public class MySingleLinkedList<T> extends AbstractSequentialList<T> {
    private Node<T> header;
    private Node<T> end;
    private int size;
    private int count;
    // used for iterator
    
    /**
     *The default constructor.
     */
    public MySingleLinkedList() {
        header = new Node<T>();
        end = header;
        size = 0;
    }
    
    public int size() {
        return size;
    }// end size
    
    public ListIterator<T> listIterator(int index) {
        return new MyListIterator<T>(header,index);
    }
    
    private static class Node<E> {
        E data;
        Node<E> next;
        Node() {}
        
        Node(E data) {
            this.data = data;
        }// end constructor
        
        Node(E data, Node<E> next) {
            this.data = data;
            this.next = next;
        }// end constructor
    }// end class
    
    private class MyListIterator<C> implements ListIterator<C> {
        Node<C> header;
        Node<C> current;
        Node<C> previous;
        Node<C> lastReturned;
        Node<C> p;
        boolean removeOK;
        boolean setOK;
        boolean lastMovePrevious;
        int index;
        
        public MyListIterator(Node<C> header,int index) {
            this.header = header;
            current = header;
            for(int i = 0; i < index; i++ ) {
                current = current.next;
            }
            this.index = index-1;
            removeOK = false;
            setOK = false;
        }
        
        public boolean hasNext() {
            return current.next != null;
        }
        
        public boolean hasPrevious() {
            return current != header;
        }
        
        public C next() {
            if( current.next == null ) throw new NoSuchElementException();
            index++;
            removeOK = true;
            setOK = true;
            previous = current;
            current = current.next;
            lastReturned = current;
            lastMovePrevious = false;
            return current.data;
        }
        
        public C previous() {
            if( current == header ) throw new NoSuchElementException();
            index--;
            removeOK = true;
            setOK = true;
            previous = header;
            p = header;
            while( p.next != current ) {
                previous = p;
                p = p.next;
            }// end while
            current = p;
            lastMovePrevious = true;
            lastReturned = current.next;
            return current.next.data;
        }
        
        public void add(C x) {
            current.next = new Node<C>(x,current.next);
            current = current.next;
            setOK = false;
            removeOK = false;
            index++;
            size++;
        }
        
        public void set(C x) {
            if( !setOK ) throw new NoSuchElementException();
            lastReturned.data = x;
        }
        
        public void remove() {
            if( !removeOK ) throw new NoSuchElementException();
            removeOK = false;
            setOK = false;
            if( lastMovePrevious ) {
                current.next = current.next.next;
            } else {
                previous.next = previous.next.next;
                current = previous;
                index--;
            }// end if
            size--;
        }//end remove
        
        public int nextIndex() {
            return index+1;
        }
        
        public int previousIndex() {
            return index;
        }
        
    } // end MyListIterator
    
} // MySingleLinkedList



