package cpsc2150.MyVector;

/**
 * <p>
 * An array implementation of {@link IVector}.
 * </p>
 *
 * @invariant 0 <= myVector.size() <= MAX_LENGTH
 *
 * @correspondence self = [myVector represented as a sequence of values]
 */
public class ArrayVector<T> extends AbsVector<T> implements IVector<T> {

    // ===========================================================
    // Member Fields
    // ===========================================================

    /**
     * <p>
     * this time store the vector in an array. myVector[0] is the front of the vector
     * </p>
     */
    private T[] myVector;

    // ===========================================================
    // Constructors
    // ===========================================================

    /**
     * <p>
     * This creates a new array-based vector that is initially empty.
     * </p>
     *
     * @pre None
     *
     * @post myVector = [a value array of MAX_LENGTH]
     */
    @SuppressWarnings("unchecked")
    public ArrayVector() {

        // Initialize myVector as an Object array with size MAX_LENGTH, typecast to T
        myVector = (T[]) new Object[MAX_LENGTH];

    }

    // ===========================================================
    // Public Methods
    // ===========================================================

    @Override
    public void addElement(T val) {

        // Set the last unused value of the vector to the new value by getting the length of the vector
        myVector[length()] = val;

    }

    @Override
    @SuppressWarnings("unchecked")
    public T removeElement() {

        // Store the first value in myVector
        T removed = myVector[0];

        // Create and initialize a new vector
        T[] newVector = (T[]) new Object[MAX_LENGTH];

        // Loop through every index of myVector starting at index 1
        for (int i = START_POS; i < MAX_LENGTH; i++) {

            // Set the value at the index before the current index in newVector to the
            // value at the current index in myVector
            newVector[i - START_POS] = myVector[i];

        }

        // Set myVector to newVector
        myVector = newVector;

        return removed;

    }

    @Override
    public boolean contains(T val) {

        // Loop through every index of myVector
        for (int i = 0; i < length(); i++) {

            // Compare the current value in myVector to the value being searched for
            // If a match is found, return true
            if (myVector[i].equals(val)) {

                return true;

            }

        }

        // If function execution has made it this far, there is no match so return false
        return false;

    }

    @Override
    public T get(int pos) {

        // Return the item at the position in the Vector, minus 1 since the Vector is implemented as an array
        return myVector[pos - START_POS];

    }

    @Override
    public int length() {

        // Variable to hold a running count of items
        int count = 0;

        // Loop through every index of myVector
        for (int i = 0; i < MAX_LENGTH; i++) {

            // If the current value in myVector is not null, increment count
            if (myVector[i] != null) {

                count++;

            }

        }

        return count;

    }

    @Override
    @SuppressWarnings("unchecked")
    public void clear() {

        // Re-initialize myVector
        myVector = (T[]) new Object[MAX_LENGTH];

    }

}
