package labs.iterators;


import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Class that represents a ordered collection of Strings, potentially containing null entries.
 * Iteration skips any null elements.
 *
 * @author CS 240 Instructors
 */
public class GapList implements Iterable<String> {

  private final String[] elements;
  private int size;

  /**
   * Constructor that initializes the GapList with a given capacity.
   *
   * @param capacity The initial capacity of the GapList.
   */
  public GapList(int capacity) {
    this.elements = new String[capacity];
    this.size = 0;
  }

  private void checkBounds(int i) {
    if (i < 0 || i >= elements.length) {
      throw new IndexOutOfBoundsException(i);
    }
  }

  /**
   * Store a string at the specified index.
   *
   * @param index The index where the string should be stored.
   * @param value The string to store.
   * @throws IndexOutOfBoundsException if the index is out of bounds.
   */
  public void add(int index, String value) {
    checkBounds(index);
    if (elements[index] == null && value != null) {
      size++;
    }
    if (elements[index] != null && value == null) {
      size--;
    }
    elements[index] = value;
  }

  /**
   * Get the string at the specified index.
   *
   * @param index The index of the string to retrieve.
   * @return The string at the specified index.
   * @throws IndexOutOfBoundsException if the index is out of bounds.
   */
  public String get(int index) {
    checkBounds(index);
    return elements[index];
  }


  /**
   * Return the number of elements stored in the collection, not including nulls.
   */
  public int size() {
    return size;
  }

  /**
   * Return the capacity of the collection.
   */
  public int capacity() {
    return elements.length;
  }

  /**
   * @return an appropriate iterator object
   */
  public Iterator<String> iterator() {
    return new GapListIterator();
  }

  // -----------------------------------------------------------
  // GapListIterator is a private inner class: it can only be instantiated by
  // GapList.
  // --------------------------------------------------------------
  private class GapListIterator implements Iterator<String> {

    /*
     * Note that Iterators are just normal Java classes, and can have constructors. However, it is
     * fairly common to just initialize the instance variables when they are declared.
     */
    int index;

    /**
     * Initialize the index to the first occupied array position.
     *
     * @param elements The array to iterate over.
     */
    private GapListIterator() {
      index = 0;
    }

    /** Move the index forward to the next non-null entry. */
    private void advance() {
      while (index < elements.length && elements[index] == null) {
        index++;
      }
    }

    /**
     * @return true if there are more strings to return
     */
    public boolean hasNext() {
      advance();
      return index < elements.length;
    }

    /**
     * Return the next string and update the index.
     */
    public String next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }

      return elements[index++];
    }

    /**
     * Not implemented.
     */
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
}
