package memberclass2;

import java.util.AbstractList;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Eine simple verlinkte Liste, die eine member class verwendet, um einen Iterator zu erzeugen.
 *   
 * @author Ralf Kunze (rkunze@uos.de), Institut fuer Informatik, Universitaet
 *         Osnabrueck
 * @date 21.05.2007
 */
@SuppressWarnings("unchecked")
public class MyList extends AbstractList {

	private MyListEntry element;

	private static class MyListEntry {

		private Object value;

		private MyListEntry next;

		private MyListEntry previous;

		MyListEntry() {
			value = next = previous = null;
		}

		MyListEntry(Object value) {
			next = previous = null;
			this.value = value;
		}

		MyListEntry(MyListEntry previous, Object value, MyListEntry next) {
			this.previous = previous;
			this.value = value;
			this.next = next;
		}
	}

	/**
	 * Leere Liste erzeugen.
	 */
	public MyList() {
		element = null;
	}

	/**
	 * Element vor dem aktuellen einfuegen. Das eingefuegte Element wird zum aktuellen. 
	 */
	public boolean add(Object o) {
		if (element == null) {
			element = new MyListEntry(o);
		} else if (element.previous == null) {
			element.previous = new MyListEntry(null, o, element); // Wird
			element = element.previous; 							// automatisch
																// verkettet
		} else {
			MyListEntry newElement = new MyListEntry(element.previous, o,
					element);
			element.previous.next = newElement;
			element.previous = newElement;
			element = element.previous;
		}

		return true; // Einfuegen klappt immer
	}

	/**
	 * Liefert eine Stringrepraesentation der Liste
	 */
	public String toString() {

		if (element == null)
			return "[]";

		MyListEntry tmp = element;
		while (tmp.previous != null) {
			tmp = tmp.previous;
		}

		StringBuilder sb = new StringBuilder("[");

		while (tmp.next != null) {
			sb.append(tmp.value).append(",");
			tmp = tmp.next;
		}
		sb.append(tmp.value);
		sb.append("]");

		return sb.toString();
	}

	@Override
	public Object get(int index) {
		if (element == null)
			return null;

		MyListEntry tmp = element;
		while (tmp.previous != null) {
			tmp = tmp.previous;
		}

		while (tmp.next != null && index > 0) {
			tmp = tmp.next;
			index--;
		}

		if (index != 0)
			return null;
		else
			return tmp.value;
	}

	@Override
	public int size() {
		if (element == null)
			return 0;

		MyListEntry tmp = element;
		while (tmp.previous != null) {
			tmp = tmp.previous;
		}

		int counter = 1;
		while (tmp.next != null) {
			tmp = tmp.next;
			counter++;
		}
		return counter;
	}

	/**
	 * Liefert einen Iterator zurueck.
	 */
	public Iterator iterator() {
		return new MyListIterator(); // Ist gleich zu this.new MyListIterator();
	}

	/**
	 * Member class, damit der Iterator auf die Elemente der Liste zugreifen darf.
	 * 
	 * @author  Ralf Kunze (rkunze@uos.de), Institut fuer Informatik, Universitaet Osnabrueck
	 * @date 22.05.2007
	 */
	class MyListIterator implements Iterator {

		private MyListEntry tmp;

		MyListIterator() {
			tmp = element;
			if (tmp != null)
				while (tmp.previous != null) {
					tmp = tmp.previous;
				}
		}

		public boolean hasNext() {
			return tmp != null;
		}

		public Object next() {

			if (tmp != null) {
				Object o = tmp.value;
				tmp = tmp.next;
				return o;
			} else
				throw new NoSuchElementException("Kein Element da");
		}

		public void remove() {
			throw new UnsupportedOperationException();

		}

	}
}
