package cpsc2150.MyDeque;

import java.util.*;

/**
 * Class that implements the IDeque interface using an array.
 *
 * @invariant
 *      0 {@code <=} myQ.size() {@code <=} MAX_LENGTH
 *
 * @correspondance
 *      length_of_deque = myQ.size() AND
 *      self = myQ.get(0...myQ.size()-1)
 */
public class ListDeque<T> extends AbsDeque<T> implements IDeque<T> {

    // This time store the deque in a list
    // myQ.get(0) is the front of the deque
    private List<T> myQ;

    /**
     * Constructor for ListDeque that creates an "empty" deque with a maximum length of 100.
     *
     * @post
     *      myQ.size() = 0 AND myQ = ArrayList<Object>
     */
    public ListDeque() {

        // Initialize myQ as an ArrayList of Objects
        myQ = new ArrayList<T>();

    }

    /**
     * Adds x to the end of the deque.
     *
     * @param x Object to be added to end of deque
     *
     * @pre
     *      length of myQ, |myQ| {@code <} MAX_LENGTH
     *
     * @post
     *      myQ = [ x added to the end of #myQ ] AND
     *      length of myQ, |myQ| = length of #myQ, |#myQ| + 1
     */
    public void enqueue(T x) {

        // Call ArrayList add method
        myQ.add(x);

    }

    /**
     * Removes and returns the object at the front of the deque.
     *
     * @return Object at the front of deque
     *
     * @pre
     *      length of myQ, |myQ| {@code >} 0
     *
     * @post
     *      dequeue = [ object at the front of #myQ ] AND
     *      myQ = [ dequeue removed from the front of #myQ ] AND
     *      length of myQ, |myQ| = length of #myQ, |#myQ| - 1
     */
    public T dequeue() {

        // Call ArrayList get method at index 0
        T removed = myQ.get(0);

        // Call ArrayList remove method at index 0
        myQ.remove(0);

        return removed;

    }

    /**
     * Adds x to the front of the deque.
     *
     * @param x Object to be added to front of deque
     *
     * @pre
     *      length of self, |self| {@code <} MAX_LENGTH
     *
     * @post
     *      myQ = [ x added to the front of #myQ ] AND
     *      length of myQ, |myQ| = length of #myQ, |#myQ| + 1
     */
    public void inject(T x) {

        // Call ArrayList add method at index 0
        myQ.add(0, x);

    }

    /**
     * Removes and returns the object at the end of the deque.
     *
     * @return Object at the end of deque
     *
     * @pre
     *      length of self, |self| {@code >} 0
     *
     * @post
     *      removeLast = [ object at the end of #myQ ] AND
     *      myQ = [ removeLast removed from the end of #myQ ] AND
     *      length of myQ, |myQ| = length of #myQ, |#myQ| - 1
     */
    public T removeLast() {

        // Call ArrayList get method at last index
        T removed = myQ.get(myQ.size() - 1);

        // Call ArrayList remove method at last index
        myQ.remove(myQ.size() - 1);

        return removed;

    }

    /**
     * Returns the number of objects in the deque.
     *
     * @return The number of objects in the deque
     *
     * @post
     *      length = [ size of #myQ ] AND
     *      myQ = #myQ
     */
    public int length() {

        // Call ArrayList size method
        return myQ.size();

    }

    /**
     * Clears the entire deque.
     *
     * @post
     *      self = {@code <>}
     */
    public void clear() {

        // Call ArrayList clear method
        myQ.clear();

    }

}