import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Queue;
import java.util.Iterator;

public class Example4Solved {

    // Complete this class
    private class PeekingIterator<T> implements Iterator<T>
    {
        // Instance variables
        private Iterator<T> original_iterator;
        private T           buffer;
        
        public PeekingIterator(Iterator<T> it) {
            original_iterator = it;
            buffer = null;
        }
        public boolean hasNext() {
            // we have a next element in two situations
            // - either there is an element in the buffer
            // - or the iterator hasNext is true
            return (buffer != null) || (original_iterator.hasNext());
        }
        public T next() {
            T result;
            if (buffer != null) {
                // we have an element in the buffer
                result = buffer;
                buffer = null; // make sure to set to null so
                               // we don't revisit this item
            } else {
                // we do not have an element in the buffer
                result = original_iterator.next();
            }
            return result;
        }
        public T peek() {
            // if no element is buffered, then try to fill the buffer
            if (buffer == null)
                buffer = original_iterator.next();

            // now that we have guaranteed buffer is not empty, return contents
            return buffer;
        }
        public void remove() { throw new RuntimeException("not implemented"); }
    }


    public static void main(String[] args) {
        Queue<String> q = new Queue<String>();
        q.enqueue("hello");
        q.enqueue("world");
        q.enqueue("!");

        // Two ways of iterating over the objects of q.
        Iterator<String> iterator = new PeekingIterator(q.iterator());
        
        StdOut.println(iterator);
        StdOut.println(iterator.hasNext());
        StdOut.println(iterator.next());
        StdOut.println(iterator.peek());
        StdOut.println(iterator.peek());
        StdOut.println(iterator.hasNext());
        StdOut.println(iterator.next());
    }
    
}