package cpsc2150.MyDeque;

/**
 * Class that implements the IDeque interface using an array.
 *
 * @invariant
 *      length of myQ, |myQ| {@code <} MAX_LENGTH AND
 *      0 {@code <=} myLength {@code <=} MAX_LENGTH
 *
 *
 * @correspondance
 *      length_of_deque = myLength AND
 *      self = myQ[0...myLength-1]
 */
public class ArrayDeque implements IDeque {

    // Where the data is stored
    // myQ[0] is the front of the deque
    private Integer[] myQ;

    // Tracks how many items are in the deque
    // Also used to find the end of the deque
    private int myLength;

    /**
     * Constructor for ArrayDeque that creates an "empty" deque with a maximum length of 100.
     *
     * @pre
     *      0 {@code <=} myLength {@code <=} MAX_LENGTH AND
     *      [ myQ is uninitialized ]
     *
     * @post
     *      myLength = 0 AND myQ = Integer[MAX_LENGTH]
     */
    public ArrayDeque() {

        // Set myLength to 0
        myLength = 0;
        // Initialize myQ as an Integer array of size MAX_LENGTH
        myQ = new Integer[MAX_LENGTH];

    }

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

        // Create temp array of Integers with size of myLength plus 1
        Integer[] temp = new Integer[myLength + 1];

        // Loop through myQ
        for (int i = 0; i < myLength; i++) {

            temp[i] = myQ[i];

        }
        // Set the last value of temp to x
        temp[myLength] = x;

        // Set myQ equal to temp
        myQ = temp;

        // Increment myLength
        myLength++;

    }

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

        // Store the value being removed
        int removed = myQ[0];

        // Create temp array of Integers with size of myLength minus 1
        Integer[] temp = new Integer[myLength - 1];

        // Loop through myQ
        for (int i = 1; i < myLength; i++) {

            temp[i - 1] = myQ[i];

        }

        // Set myQ equal to temp
        myQ = temp;

        // Decrement myLength
        myLength--;

        return removed;

    }

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

        // Create temp array of Integers with size of myLength plus 1
        Integer[] temp = new Integer[myLength + 1];

        // Set the first value of temp to x
        temp[0] = x;
        // Loop through myQ
        for (int i = 0; i < myLength; i++) {

            temp[i + 1] = myQ[i];

        }

        // Set myQ equal to temp
        myQ = temp;

        // Increment myLength
        myLength++;

    }

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

        // Store the value being removed
        int removed = myQ[myLength - 1];

        // Create temp array of Integers with size of myLength minus 1
        Integer[] temp = new Integer[myLength - 1];

        // Loop through myQ minus the last index
        for (int i = 0; i < (myLength - 1); i++) {

            temp[i] = myQ[i];

        }

        // Set myQ equal to temp
        myQ = temp;

        // Decrement myLength
        myLength--;

        return removed;

    }

    /**
     * Returns the number of integers in the deque.
     *
     * @return The number of integers in the deque
     *
     * @post
     *      length = myLength AND myLength = #myLength AND
     *      myQ = #myQ
     */
    public int length() {

        return myLength;

    }

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

        // Create temp array of Integers with size of MAX_LENGTH
        Integer[] temp = new Integer[MAX_LENGTH];

        // Set myQ equal to temp
        myQ = temp;

        // Set myLength to 0
        myLength = 0;

    }

}