package projectEQ2440.utils;

/**
 * <b>public class Queue&lt;E&gt;</b><br/>
 * Class to manage a queue of element
 * 
 * @param <E> : the type of the element in the queue
 */
public class Queue<E> {
	
	// Array of messages 
	private Element first;
	private Element last;
	
	// Length of messages
	private int length;
	
	/**
	 * <b>public Queue()</b><br/>
	 * Constructor initializing the queue 
	 */
	public Queue() {
		first = null;
		last = null;
		length = 0;
	}
	
	/**
	 * <b>public synchronized int length()</b><br/>
	 * Gives the length of the queue
	 * 
	 * @return : the length of the queue
	 */
	public synchronized int length() {
		return length;
	}
	
	/**
	 * <b>public synchronized void add(E element)</b><br/>
	 * Add an element at the end of the queue
	 * 
	 * @param element : the element to add
	 */
	public synchronized void add(E element) {
		Element tmp = new Element(element);
		if (last == null) first = tmp;
		else last.setNext(tmp);
		last = tmp;
		length++;
	}
	
	/**
	 * <b>public synchronized E pop()</b><br/>
	 * take out the first element of the queue 
	 * 
	 * @return the element taken out
	 */
	public synchronized E pop() {
		if (length == 0) return null;
		
		E result = first.getElement();
		first = first.getNext();
		length--;
		
		if (first == null) last = null;
		
		return result;
	}
	
	/**
	 * <b>public synchronized void clean()</b><br/>
	 * Remove every element of the queue
	 */
	public synchronized void clean() {
		first = null;
		last = null;
		length = 0;
	}
	
	/**
	 * <b>private class Element</b><br/>
	 * private clas to manage the element in the queue
	 */
	private class Element {
		
		// The element saved in the queue
		private E element;
		
		// The next <i>Element</i> in the queue
		private Element next;
		
		/**
		 * <b>public Element(E element)</b><br/>
		 * Constructor to put an element in <i>Element</i>
		 * 
		 * @param element : the <i>E</i> element to put in it
		 */
		public Element(E element) {
			this.element = element;
			this.next = null;
		}
		
		/**
		 * <b>public E getElement()</b><br/>
		 * Get the <i>E</i> element in the <i>Element</i>
		 * 
		 * @return the <i>E</i> element in it
		 */
		public E getElement() {
			return element;
		}
		
		/**
		 * <b>public void setNext(Element next)</b><br/>
		 * Set the next <i>Element</i>
		 * 
		 * @param next : the next <i>Element</i>
		 */
		public void setNext(Element next) {
			this.next = next;
		}
		
		/**
		 * <b>public Element getNext()</b><br/>
		 * get the next <i>Element</i>
		 * 
		 * @return the next <i>Element</i>
		 */
		public Element getNext() {
			return next;
		}
		
	}
	
}
