/**
 * ArrayStack is an implimentation of a stack that uses an array
 * as a tool to perform the basic operations a stack needs to
 * perform.
 * 
 * @author Michael Thomas Rivers
 * @version 1.0
 **/
 
public class ArrayStack implements StackADT
{
    private int top = -1;                        // points to the index of the top item
    private Object[] stack = null;               // gives us an empty array called stack
    public static final int DEFAULT_SIZE = 100;  // default size of the array used
    
    /*
     * This default constructor creates an array to be used of size 100
     */
    public ArrayStack()
    {
        stack = new Object[DEFAULT_SIZE];
    }

    /*
     * This constructor lets the user input a starting size for the size of the stack
     */
    public ArrayStack(int starting_size)
    {
        stack = new Object[starting_size];
    }
    
    /*
     * "push" will add an item onto the top of the stack
     */
    public Object push ( Object newItem )
    {
        // Confirm item isvalid
        if ( newItem == null )
        {
            return null ;
        }
        // Increase size of array if full
        if ( top + 1 >= stack.length )
        {
            growArray ( ) ;
        }
        // Move top index
        ++top ;
        // Put item in array
        stack[top] = newItem ;
        return newItem ;
    }
    
    /*
     * "pop" removes the top item from the stack and decrements the stack
     */
    public Object pop() throws EmptyStackException
    {
        try
        {
            if(isEmpty())
                throw new EmptyStackException();
                Object item = stack[ top ];
                //Object item = stack[ top ];
                stack[ top ] = null;
                --top;
                return item ;
        }
        catch( EmptyStackException e )
        {
            
        }
        return null;
    }
    
    /*
     * "peek" returns the top item of the stack
     */
    public Object peek ( )
    {
        if ( isEmpty ( ) )
        {
            return null ;
        }
        return stack [ top ] ;
    }
    
    /*
     * "isEmpty" returns a boolean (an empty stack returns true)
     */
    public boolean isEmpty ( )
    {
        return top < 0;
    }
    
    /*
     * "clear" removes all objects from the stack
     */
    public void clear ( )
    {
        if ( ! isEmpty ( ) )
        {
            java.util.Arrays.fill( stack , 0 , top , null ) ;
            top = -1;
        }
    }
    
    /*
     * "growArray" grows the stack when the stack becomes full
     */
    private int growAmount = 100;
    private void growArray ( )
    {
        Object [ ] newStack = new Object [ stack.length + growAmount ] ;
        // Manually copy in a loop , or use the native ( rather
        // than virtual machine code ) and faster , arraycopy
        System.arraycopy(stack, 0 , newStack , 0 , top + 1 ) ;
        stack = newStack ;
    }
    
}
