/**
 * A Vroomba models a virtual robotic vacuum cleaner.
 * <p>
 * Vroombas are usually used to clean a {@link Room}.
 * A Vroomba is always on, so any DIRT it moves over is always removed,
 * leaving spotlessly clean FLOORs behind!
 * <p>
 * A Vroomba moves in a turn-based way, deciding which direction to
 * head next each time its move method is called.  Because its sensors
 * are short-ranged, the move method only tells the Vroomba what is in
 * its surrounding 8 "squares".
 * <p>
 * A Vroomba may or may not try to internally map the room based on the
 * information it receives each move/turn.  When a Vroomba believes the room
 * to be clean, it may decline to move further.  Not all Vroombas stop on
 * their own, however; some just keep cleaning until turned off.
 * <p>
 * A variety of different Vroombas can be created by extending this class.
 *
 * @see Room
 * @see Direction
 *
 * @author Zach Tomaszewski
 * @version 08 Nov 2008
 */
public class Vroomba {

  /**
   * Provides this Vroomba its current surroundings and asks it to
   * choose a direction to move.
   * <p>
   * The surroundings should contain 8 entries, for
   * <code>surroundings[Direction.N.ordinal()],
   * surroundings[Direction.NE.ordinal()], surroundings[Direction.E.ordinal()],
   * ... surroundings[Direction.NW.ordinal()].
   * Each character contained should be a valid feature of a Room.
   * <p>
   * This Vroomba will then return the Direction it would like to move.
   * If it no longer wishes to move (usually because it believes its containing
   * Room is clean), it may return Direction.HERE to stop.
   * <p>
   * This behavior will depend on the overriding performed by any specific,
   * extending Vroomba.  This default Vroomba always returns Direction.HERE.
   *
   * @throws IllegalArgument  if the passed surroundings are invalid
   */
  public Direction move(char[] surroundings) throws IllegalArgumentException {
    this.validateSurroundings(surroundings);  //will throw an IAE if anything wrong

    //decide here out how to move...
    //...but this default Vroomba just powers off
    return Direction.HERE;
  }

  /**
   * Instructs this Vroomba to reset itself, such as when it is being
   * transferred to a new room.
   * <p>
   * This method currently does nothing.  It needs to be overridden only
   * by Vroombas that attempt to maintain state about the room they are
   * currently in.
   */
  public void reset() {
  }

  /**
   * Handy for double-checking that passed surroundings are valid
   * (though the only reason they wouldn't be is programmer error somewhere).
   * <p>
   * Returns if everything's fine, or throws an IllegalArgumentException if not.
   *
   * @see #move
   */
  protected void validateSurroundings(char[] surroundings)
                                     throws IllegalArgumentException {
    if (surroundings.length != 8) {
      throw new IllegalArgumentException("Surroundings array the wrong length (" +
                                         surroundings.length + " instead of 8)");
    }
    for (int i = 0; i < surroundings.length; i++) {
      switch (surroundings[i]) {
        //XXX: A Vroomba currently can't handle seeing another version of itself
        case Room.FLOOR:
        case Room.DIRT:
        case Room.WALL:
        case Room.DROP:
          break;  //good
        default:
          throw new IllegalArgumentException("Invalid character in surroundings (" +
                                            surroundings[i] + ")");
      }
    }
    return; //array was fine
  }

}
