package horstmann.ch08_queue;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator;

/**
    A first-in, first-out bounded collection of objects.
 */
public class BoundedQueue<E> extends AbstractCollection<E>
{
	/**
       Constructs an empty queue.
       @param capacity the maximum capacity of the queue
       <p><b>Precondition:</b> capacity > 0</p>
	 */
	public BoundedQueue(int capacity)
	{
		elements = new ArrayList<E>(capacity);
		count = 0;
		head = 0;
		tail = 0;
	}

	public Iterator<E> iterator()
	{
		return new
				Iterator<E>()
		{
			public boolean hasNext()
			{
				return visited < count;
			}

			public E next()
			{
				int index = (head + visited) % elements.size();
				E r = elements.get(index);
				visited++;
				return r;
			}

			public void remove()
			{
				throw new UnsupportedOperationException();
			}

			private int visited = 0;
		};
	}

	/**
       Remove object at head.
       @return the object that has been removed from the queue
       <p><b>Precondition:</b> size() > 0</p>
	 */
	public E remove()
	{
		E r = elements.get(head);
		head = (head + 1) % elements.size();
		count--;
		return r;
	}

	/**
       Append an object at tail.
       @param anObject the object to be appended
       @return true since this operation modifies the queue.
       (This is a requirement of the collections framework.)
       <p><b>Precondition:</b> !isFull()</p>
	 */
	public boolean add(E anObject)
	{
		elements.set(tail,anObject);
		tail = (tail + 1) % elements.size();
		count++;
		return true;
	}

	public int size()
	{
		return count;
	}

	/**
       Checks whether this queue is full.
       @return true if the queue is full
	 */
	public boolean isFull()
	{
		return count == elements.size();
	}

	/**
       Gets object at head.
       @return the object that is at the head of the queue
       <p><b>Precondition:</b> size() > 0</p>
	 */
	public E peek()
	{
		return elements.get(head);
	}

	private ArrayList<E> elements;
	private int head;
	private int tail;
	private int count;
}
