package com.hithomelabs.princeton1.module4;
import java.util.Iterator;
import javax.annotation.Nonnull;

// Concrete implementation of stack using arrays
// Creating a generic stack of type E
public class ArrayStack<E> extends Stack<E> {

    E[] stackArray = (E[]) new Object[1];
    private int index = 0;
    private int arrayLength = stackArray.length;

    @Override
    public boolean isEmpty() {
        return index == 0;
    }

    @Override
    public void push(E element) {
        if(index == arrayLength){
            changeArraySize(arrayLength*2);
        }
        stackArray[index] = element;
        index++;
    }

    @Override
    public E pop() {
        if(index == 0){
            return null;
        }
        index--;
        if(index < arrayLength/4){
            changeArraySize(arrayLength/2);
        }
        E temp = stackArray[index];
        stackArray[index] = null;
        return temp;
    }

    @Override
    public int size() {
        return index;
    }

    @Nonnull
    @Override
    public Iterator<E> iterator() {
        return new StackIterator();
    }

    private void changeArraySize(int intendedSize){
        E[] tempArray = stackArray;
        int oldArraySize = stackArray.length;
        stackArray = (E[]) new Object[intendedSize];
        arrayLength = stackArray.length;
        System.arraycopy(tempArray, 0, stackArray, 0, Math.min(oldArraySize, arrayLength));
    }

    private class StackIterator implements Iterator<E>{
        private int iteratorIndex = 0;

        @Override
        public boolean hasNext() {
            return stackArray[iteratorIndex] != null;
        }

        @Override
        public E next() {
            return stackArray[iteratorIndex++];
        }
    }
}
