/**
 * An array-based implementation of lists.
 *
 * @author CSC153 2003S
 * @version 1.0 of April 2003
 */
public class ArrayList
  implements List
{
  // +--------------+-----------------------------------
  // | Design Notes |
  // +--------------+

  /*
     All elements in the list are stored in positions
     0 ... size-1 of the array.  [Option: Keep spaces
     "empty"; seems harder.]

     What happens when we exceed the capacity of the
     array?
     * Throw an exception.  Well ... we didn't say that
       add could throw exceptions.
     * Expand the array when there's too much data.

     How can we delete an element?
     * Shove everything left one element and reduce the size
     * Shove the last element in the "space" and reduce
       the size.
     The first strategy is necessary for ordered lists,
     but we have not guaranteed that the list is ordered.

     Note that we clear "pointers" whenever possible so
     that the Java Runtime can get rid of things we don't
     care about.

     The idiots who designed the List interface should have
     had permitted advance to throw an exception.
     Then we could have written cool code like
     try {
       while (true) {
         System.out.println(cursor.getValue());
         cursor.advance();
       }
     }
     catch (Exception e) { }
   */


  // +--------+-----------------------------------------
  // | Fields |
  // +--------+

  /** 
   * The contents of the list (plus some extra free space).
   */
  Object[] contents;

  /**
   * How many elements are actually in the array.
   */
  int size;


  // +--------------+-----------------------------------
  // | Constructors |
  // +--------------+

  /** Create a new list. */
  public ArrayList() {
    this.construct(13);
  } // ArrayList()

  /** Create a new list that easily holds n elements. */
  public ArrayList(int n) {
    this.construct(n);
  } // ArrayList(int)

  /** Create a new list that easily holds n elements. */
  private void construct(int n) {
    this.size = 0; 
    this.contents = new Object[n];
  } // construct(int)


  // +--------------+-----------------------------------
  // | List Methods |
  // +--------------+

  /**
   * Get the cursor for stepping through the list.
   * Precondition:
   *   The list is nonempty.
   */
  public Cursor getCursor() {
    return new ListArrayCursor(0);
  } // getCursor()

  /**
   * Add an element somewhere in the list.
   */
  public void add(Object val) {
    // Verify that there's enough room
    this.ensureCapacity();
    // Add the object at position size
    this.contents[this.size] = val;
  } // add(Object)

  /**
   * Determine how many elements are in the list.
   */
  public int length() {
    return this.size;
  } // length()

  /**
   * Determine whether the list is empty.
   */
  public boolean isEmpty() {
    return 0 == this.size;
  } // isEmpty()

  // +-----------------+--------------------------------
  // | Private Methods |
  // +-----------------+

  /**
   * Ensure that the capacity is big enough.  Expand
   * if necessary.
   */
  private void ensureCapacity() {
    if (this.size == this.contents.length) {
    } //
  } // ensureCapacity

} // class ArrayList


/**
 * A cursor for an array-based implementation of lists.
 *
 * @author CSC153 2003S
 * @version 1.0 of April 2003
 */
class ArrayListCursor
  implements Cursor
{
  // +--------+-----------------------------------------
  // | Fields |
  // +--------+

  /** The position of the cursor. */
  int pos;

  /** The list we're going through. */
  ArrayList base;


  // +--------------+-----------------------------------
  // | Constructors |
  // +--------------+

  // +--------------+-----------------------------------
  // | List Methods |
  // +--------------+

  /**
   * Get the value associated with the cursor.
   * Preconditions:
   *   The cursor is at a valid position.  (See delete().)
   */
  public Object getValue() {
    return this.base.contents[this.pos];
  } // getValue()

  /**
   * Advance the cursor to the next value.
   * Preconditions: 
   *   The cursor is not at the end of the list.
   *   The cursor is at a valid position.  (See delete().)
   */
  public void advance() {
    this.pos++;
  } // advance()

  /**
   * Move the cursor backwards to the previous value.
   * Preconditions: 
   *   The cursor is not at the beginning of the list.
   *   The cursor is at a valid position.  (See delete().)
   */
  public void retreat() {
  }

  /**
   * Delete the value associated with the cursor.
   * Preconditions:
   *   The cursor is at a valid position.  
   * Postconditions:
   *   The value associated with the cursor is no longer in the list.
   *   The list is now one element shorter.
   *   All cursors associated with the list are now at unknown
   *     (invalid) positions.
   * @return
   *   The deleted object.
   */
  public Object delete() {
    Object tmp = this.base.contents[this.pos];
    this.base.contents[this.pos] =
      this.base.contents[this.base.size-1];
    this.base.contents[this.base.size-1] = null;
    --this.base.size;
    return tmp;
  } // delete()

  /**
   * Determine if the cursor is at the end of the list.
   * Preconditions:
   *   The cursor is at a valid position (see delete).
   * @return
   *   True, if the cursor is at the end of the list.
   *   False, otherwise.
   */
  public boolean atEnd() {
    return this.pos == this.base.size-1;
  }

  /**
   * Determine if the cursor is at the front of the list.
   * Preconditions:
   *   The cursor is at a valid position (see delete).
   * @return
   *   True, if the cursor is at the front of the list.
   *   False, otherwise.
   */
  public boolean atFront() {
    
  }

  /**
   * Move the cursor to the end of the list.
   * Preconditions:
   *   The list is nonempty.
   * Postconditions:
   *   The cursor is now at a valid position.
   *   The cursor is now at the end of the list (so atEnd returns
   *     true).
   */
  public void toEnd() {
  }

  /**
   * Move the cursor to the front of the list.
   * Preconditions:
   *   The list is nonempty.
   * Postconditions:
   *   The cursor is now at a valid position.
   *   The cursor is now at the front of the list (so atFront 
   *    returns true).
   */
  public void toFront() {
  }

  // +-----------------+--------------------------------
  // | Private Methods |
  // +-----------------+

} // class ArrayListCursor

