/**
 * Class that implements a queue using a singly-linked list
 *   @author Dave Reed
 *   @version 9/2/17
 */
public class LinkedQueue<E> {
    private Node<E> front;
    private Node<E> back;
    private int numNodes;
    
    /**
     * Constructs an empty queue.
     */
    public LinkedQueue() {
        this.front = null;
        this.back = null;
        this.numNodes = 0;
    }
    
    /**
     * Determines whether the queue is empty.
     *   @return true if no items currently stored in the queue 
     */
    public boolean empty() {
        return (this.size() == 0);
    }
    
    /**
     * Determines the size of the queue.
     *   @return the number of items currently stored in the queue
     */
    public int size() {
        return this.numNodes;
    }
    
    /**
     * Adds a new data value at the back of the queue.
     *   @param value the value to be added
     */
    public void add(E value) {
        Node<E> toBeAdded = new Node<E>(value, null);
        if (this.back == null) {
            this.back = toBeAdded;
            this.front = this.back;
        }
        else {
            this.back.setNext(toBeAdded);
            this.back = toBeAdded;
        }
        this.numNodes++;
    }
    
    /**
     * Removes a value from the front of the queue.
     *   @return the item previously at the front
     *   @throws java.util.EmptyStackException 
     */
    public E remove() throws java.util.NoSuchElementException {
        if (this.empty()) {
            throw(new java.util.NoSuchElementException());
        }
        else {
            E frontData = this.front.getData();
            this.front = this.front.getNext();
            if (this.front == null) {
                this.back = null;
            }
            this.numNodes--;
            return frontData;
        }
    }
    
    /**
     * Peeks at the value currently at the front of the queue.
     *   @return the item at the front
     *   @throws java.util.NoSuchElementException 
     */
    public E peek() throws java.util.NoSuchElementException {
        if (this.empty()) {
            throw(new java.util.NoSuchElementException());
        }
        else {
            return this.front.getData();           
        }
    }
    
    /////////////////////////////////////////////////////////////
    
    public static void main(String[] args) {
        LinkedQueue<Integer> nums = new LinkedQueue<Integer>();
        for (int i = 1; i <= 10; i++) {
            nums.add(i);
        }
        
        while (!nums.empty()) {
            System.out.println(nums.remove());
        }
    }
}

