/* Author: Jeff Dalton <J.Dalton@ed.ac.uk>
 * Updated: Wed May  9 18:03:09 2001 by Jeff Dalton
 */

package ix.util.lisp;

import java.util.*;

/**
 * An implementation of ListIterator for LLists.
 */
public class LListListIterator implements ListIterator {
    
    protected LList list = null;
    protected int index = 0;		// 0-origin
    protected LList at = null;		// for the next next()
    protected Cons setPoint = null; 	// anoying that this is needed /\/

    public LListListIterator(LList list) {
	this.list = list;
	this.at = list;
    }

    public LListListIterator(LList list, int start) {
	this.list = list;
	at = list;
	if (start < 0)
	    throw new IndexOutOfBoundsException();
	while (at != Lisp.NIL && index < start) {
	    at = at.cdr();
	    index++;
	}
	if (index != start)		// list too short
	    throw new IndexOutOfBoundsException();
    }

    public boolean hasNext() {
	return at != Lisp.NIL;
    }

    public Object next() {
	if (at != Lisp.NIL) {
	    Object elt = at.car();
	    setPoint = (Cons)at;
	    index++;
	    at = at.cdr();
	    return elt;
	}
	else
	    throw new NoSuchElementException("at end of LList");
    }

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

    public Object previous() {
	if (index > 0) {
	    index--;
	    at = list.drop(index);
	    setPoint = (Cons)at;
	    return at.car();
	}
	else
	    throw new NoSuchElementException("at start of LList");
    }

    public int nextIndex() {
	return index;
    }

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

    public void remove() {
	throw new UnsupportedOperationException("Cannot remove from an LList");
    }

    public void set(Object o) {
	if (setPoint == null)
	    throw new IllegalStateException("set without next or previous");
	else
	    setPoint.setCar(o);
    }

    public void add(Object o) {
	throw new UnsupportedOperationException("Cannot add to an LList");
    }

}
