// List.java -- partially written source file for Lab06

package lab06;

import java.awt.*;

/**
 *
 * @author J.K. Daugherty
 */
public class List {
    public static final int DEFAULT_CAPACITY = 10;
 
    // List instance variables...

    private Object [] array;    // Reference to internal array
    private int initCapacity;   // Initial capacity
    private int itemCount;      // Current size (number of stored items)
    private int cursor;         // Index of "current" value in List
                                // NOTE: cursor is not used in Lab06
    
    // Private constants used to render List...

    private static final int CELL_WIDTH = 60;
    private static final int CELL_HEIGHT = 30;
    private static final Color FILLED_CELL_COLOR
            = new Color (0xEC,0xEC,0xEC);
    private static final Color EMPTY_CELL_COLOR
            = new Color (0xB7,0xB7,0xB7);
    private static final Color ARROW_COLOR = Color.black;

    private static final int[] X_ARROW = {-4,-4,-10,0,10,4,4};
    private static final int[] Y_ARROW = {50,20,20,0, 20, 20,50};
	
    public List (int initCapacity) {
        array = new Object [initCapacity];
        this.initCapacity = initCapacity;
        itemCount = 0;
        cursor = -1;    // Indicates NO current value
    }

    /** Creates an empty List with a default initial capacity.
     */

    public List () {
        this (DEFAULT_CAPACITY);
    }    

    // --------------------------------------------------------------
    // STUBS for List methods... this is where you come in...
    // --------------------------------------------------------------

    public void add (int index, Object value)
            throws IndexOutOfBoundsException {

        // STUB -- fill in...
    }
  
    public Object set (int index, Object value)
            throws IndexOutOfBoundsException {

        // STUB -- remove line below and fill in...
        return null;
    }
  
    public Object remove (int index) throws IndexOutOfBoundsException {

        // STUB -- remove line below and fill in...
        return null;        
    }

    public Object get (int index) throws IndexOutOfBoundsException {

        // STUB -- remove line below and fill in...
        return null;
    }

    // --------------------------------------------------------------
    // END OF STUBS -- all methods below are fully implemented...
    // --------------------------------------------------------------

    /**
     * Adds the specified value to the rear of the List (appends).

     * @param value
     */
    public void add (Object value) {
        if (itemCount == array.length) {
            setCapacity (itemCount + 1);
        }
        array[itemCount] = value;
        itemCount++;
        cursor = itemCount;
    }
  
    /** Indicates whether the List is currently empty.
     *  @return true if the List is empty, false otherwise.
     */
    public boolean isEmpty () {
        return (itemCount == 0);
    }

    /** Returns the number of values currently stored in the List.
     * @return Number of stored values.
     */
    public int size () {
        return itemCount;
    }
  
    /** Returns the current capacity of the internal List array.
     * Note that this is the full length of the array, namely 
     * the number of components allocated by the new operator.
     * It does not denote the number of items currently stored in 
     * the List, which is returned by {@link #getItemCount}.
     * @return The current List capacity.
     */
    public int getCapacity () {
        return array.length;
    }
  
    /** If the requested new capacity is not sufficient to hold all
     * the values currently stored in the List, the method throws
     * an IllegalStateException without making any change to the
     * List. Otherwise, this method replaces the internal array
     * with a new array having the requested new capacity.
     * All items stored in the current array are copied to the
     * new array, and the values at the front and rear of the List
     * are the same as before.
     * @param capacity The requested new capacity.
     */
    public void setCapacity (int capacity) throws IllegalStateException {
        if (capacity < itemCount) {
            throw new IllegalStateException ("Insufficient capacity");
        }
        Object [] temp = new Object [capacity];
        
        for (int n = 0; n < itemCount; n++) {
            temp[n] = array[n];
        }

        array = temp;
    } 

    /** Removes all values stored in the List, without changing
     *  its current capacity.
     */
    public void clear () {
        itemCount = 0;
        cursor = -1;
    }
  
    /** Restores the List to its original state, just after it
     *  was constructed.
     */
    public void reset () {
        itemCount = 0;
        cursor = -1;
        array = new Object [initCapacity];
    }
  
    /** Changes the List capacity to match its current size (number
     * of stored items). Note: if the List is currently empty, its
     * capacity is set to 1 rather than 0.
     */
    public void trim () {
        if (itemCount == 0) {
            setCapacity(1);
        }
        else {
            setCapacity (itemCount);
        }
    } 

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

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

        int xbase = (panelWidth - array.length * CELL_WIDTH) / 2;
        int ybase = panelHeight / 2;

        // Find x-coordinate of upper left-hand corner of each cell
        
        int xloc = xbase;
        int yloc = ybase - CELL_HEIGHT / 2;

        for (int i = 0; i < itemCount; i++) {
            g.setColor (FILLED_CELL_COLOR);
            g.fill3DRect(xloc + i * CELL_WIDTH, yloc,
                   CELL_WIDTH, CELL_HEIGHT, true);
            g.setColor (Color.black);
            g.drawString(array[i].toString(),
                 xloc + 2 + i * CELL_WIDTH, yloc + 20);

            g.drawString("" + i,
                    xloc + i * CELL_WIDTH + CELL_WIDTH / 2 - 2, yloc -10);
        }

        for (int i = itemCount; i < array.length; i++) {
            g.setColor (EMPTY_CELL_COLOR);
            g.fill3DRect(xloc + i * CELL_WIDTH, yloc,
                   CELL_WIDTH, CELL_HEIGHT, true);
            g.setColor (Color.GRAY);
            g.drawString("" + i,
                    xloc + i * CELL_WIDTH + CELL_WIDTH / 2 - 2, yloc -10);
        }

        // paintArrow (g, xbase, ybase, "Cursor", cursor);
     }
   private void paintArrow (Graphics g, int xbase, int ybase,
        String label, int index) {
        g.setColor (ARROW_COLOR);
    
        int[] xarrow = new int [X_ARROW.length];
        int[] yarrow = new int [Y_ARROW.length];
        int points = X_ARROW.length;
    
        for (int k = 0; k < points; k++) {
            xarrow[k] =  X_ARROW [k] + xbase 
                    + index * CELL_WIDTH + CELL_WIDTH / 2;
            yarrow[k] =  Y_ARROW [k] + ybase + CELL_HEIGHT;
        }

        g.fillPolygon (xarrow, yarrow, points);

        // Draw label...
    
        g.setColor (Color.black);
        Font font = new Font ("Arial", Font.BOLD, 16);
        g.setFont(font);

        g.drawString (label,
                xbase + index * CELL_WIDTH + CELL_WIDTH / 2
                    - g.getFontMetrics(font).stringWidth(label) / 2,
                ybase + Y_ARROW[0] + CELL_HEIGHT + 20);
    
        // g.setFont (currentfont);
    }

}
