// Stack.java -- partially written source file for Lab04

package lab04;

import java.awt.*;

/**
 * This version implements a Stack as a resizable array.
 *
 * @author J.K. Daugherty
 * @version 0.01
 */
public class Stack {
    public static final int DEFAULT_CAPACITY = 5;
    
    private Object [] array;
    private int top;
    private int initCapacity;

    // Constants for graphical display...
    
    public static final int CELL_WIDTH = 120;
    public static final int CELL_HEIGHT = 30;
    public static final Color FILLED_CELL_COLOR = new Color (0xEC,0xEC,0xEC);
    public static final Color EMPTY_CELL_COLOR = new Color (0xB7,0xB7,0xB7);
    public static final Color ARROW_COLOR = Color.black;

    // Dual (x,y) arrays, used to draw an arrow pointing to the top of
    // the stack. These represent relative values, where the tip of the
    // (leftward pointing) arrow is at (0,0). To render this arrow at
    // a specific location in the display window, fixed offsets must
    // be added to these values (see below).

    int[] xvalues = {0,  20,  20, 70,  70, 20, 20};
    int[] yvalues = {0, -10,  -5, -5,   5,  5, 10};
    
    /** Creates an empty Stack object whose initial array length is
     * set to the {@link #DEFAULT_CAPACITY}. */
    public Stack() {
        this (DEFAULT_CAPACITY);
    }

    /** Creates an empty Stack object, whose initial array length
     * is set by the specified parameter.
     * @param capacity The initial array length.
     */
    public Stack (int capacity) {
        initCapacity = capacity;
        array = new Object [capacity];
        top = 0;
    }

    /** Pushes the specified value onto the stack. NOTE: push()
     * first checks whether the stack is currently full, and
     * if so it automatically invokes setCapacity() to increase
     * its capacity (array length) before pushing the new value.
     *
     * @param value The object to be pushed onto the stack.
     */
    public void push (Object value) {
        // STUB -- implement this method
    }
    
    /** Pops the topmost item from the stack. The method assumes
     * as a precondition that the stack is not already empty,
     * and it throws an IllegalStateException if this is violated.
     *
     * @return The item popped from the stack.
     */
    public Object pop () throws IllegalStateException {
        // STUB -- remove line below and implement method
        return null;
    }

    /** Indicates whether the stack is empty.
     * @return True if the stack is empty, false otherwise.
     */
    public boolean isEmpty () {
        // STUB -- remove line below and implement method
        return false;
    }

     /** Sets the stack capacity (array length) to the specified value.
     * The method assumes as a precondition that the new capacity
     * is not less than the current number of stored items, and it
     * throws an IllegalStateException if this is violated.
     *
     * @param capacity The new stack array length.
     */
    public void setCapacity (int capacity) throws IllegalStateException {
	// STUB -- implement method
    }

    /** Returns the current capacity (total array length) of the stack.
     * @return The current array length.
     */
    public int getCapacity () {
        // STUB -- remove line below and implement method
	return 0;
    }

    /** Returns the original capacity (total array length) of the stack,
     * that is, its capacity when it was instantiated.
     * @return The original array length.
     */
    public int getInitCapacity () {
        // STUB -- remove line below and implement method
	return 0;
    }

    /** Returns the number of items currently stored in the stack.
     * @return The number of stored items.
     */
    public int getItemCount () {
        // STUB -- remove line below and implement method
	return 0;
    }

    /**
     * Resizes the array to match the current number of stored items,
     * leaving no unused array components. However, for the special
     * case of an empty stack, it sets the array length to be 1, not 0.
     * This convention insures that the stack will always be visible
     * in the GUI display.
     */
    public void trim () {
        // STUB -- implement method
    }

    /**
     * Removes all items currently stored on the stack, without
     * changing the current stack capacity. See also {@link #reset}.
     */
    public void clear () {
        // STUB -- implement method
    }
    
    /**
     * Removes all items currently store on the stack, and resets
     * the stack capacity to its initial value. See also {@link #clear}.
     */
    public void reset () {
        // STUB -- implement method
    }

    /** Renders the stack in a graphical display window. The window
     * dimensions and its associated graphics context
     * (java.awt.Graphics object) are both supplied as input
     * parameters.
     * @param g Graphics context associated with the display window.
     * A Graphics object provides rendering methods as well as the
     * reference frame for pixel coordinates.
     * @param panelSize Width and height of display area, in pixels.
     */

    public void render (Graphics g, Dimension panelSize) {
        int panelWidth = (int) panelSize.getWidth();
        int panelHeight = (int) panelSize.getHeight();

        // Choose horizontal "baseline" (bottom of array)
        
        int ybase = panelHeight - CELL_HEIGHT - 20; 

        // Find x-coordinate of upper left-hand corner of each cell
        
        int xloc = (panelWidth - CELL_WIDTH) / 2;

        for (int cell = 0; cell < top; cell++) {
            g.setColor (FILLED_CELL_COLOR);
            int yloc = ybase - (cell + 1) * CELL_HEIGHT;

            g.fill3DRect (xloc, yloc, CELL_WIDTH, CELL_HEIGHT, true);

            g.setColor(Color.black);
            if (cell < 10) {
                g.drawString (" " + cell, xloc - 20, yloc + CELL_HEIGHT - 10);
            }
            else {
                g.drawString ("" + cell, xloc - 20, yloc + CELL_HEIGHT - 10);
            }
            g.drawString ("" + array [cell], xloc + 10, yloc + CELL_HEIGHT - 10);
        }

        for (int cell = top; cell < array.length; cell++) {
            int yloc = ybase - (cell + 1) * CELL_HEIGHT;
            g.setColor (EMPTY_CELL_COLOR);
            g.fill3DRect (xloc, yloc, CELL_WIDTH, CELL_HEIGHT, true);
            g.setColor(Color.black);
            g.drawString ("" + cell, xloc - 15, yloc + CELL_HEIGHT - 10);
        }

        // Arrow-drawing code...

        int[] xarrow = new int[7];
        int[] yarrow = new int[7];

        for (int k = 0; k < 7; k++) {
            xarrow[k] = xvalues[k] + (panelWidth + CELL_WIDTH) / 2 + 10;
            yarrow[k] = yvalues[k] + ybase - (2 * top + 1) * CELL_HEIGHT / 2;
        }

        g.setColor (Color.black);
        g.fillPolygon (xarrow, yarrow, xarrow.length);

        // "Top" label on arrow...
    
        g.setColor(Color.black);
        Font topfont = new Font("Arial", Font.BOLD, 18);
        Font currentfont = g.getFont();
        g.setFont(topfont);
        g.drawString("Top", xarrow[3] + 10, yarrow[3] + 5 + 5);
        g.setFont(currentfont);
    }
}
