package alice.kareluser;

import org.alice.apis.moveandturn.Color;
import org.alice.apis.moveandturn.Composite;

import alice.kareltherobot.Direction;
import alice.kareltherobot.Robot;

/**
 * A robot that follows a wall using the right-hand rule and thus escapes from a maze that
 * has no traps (a connected maze).
 * 
 * @author Cay Horstmann, updated by Joe Bergin
 * 
 */
public class WallFollower extends Robot
{

	/**
	 * Create a robot on a specific street and avenue, facing a given direction with no
	 * beepers.
	 * 
	 * @param street the street on which to place the robot
	 * @param avenue the avenue on which to place the robot
	 * @param direction the direction the robot will initially face
	 */
	public WallFollower(int street, int avenue, Direction direction)
	{
		super(street, avenue, direction);

	}

	/**
	 * Create a robot on a specific street and avenue, facing a given direction with a
	 * given number of beepers.
	 * 
	 * @param street the street on which to place the robot
	 * @param avenue the avenue on which to place the robot
	 * @param direction the direction the robot will initially face
	 * @param beepers the initial number of beepers in the beeper bag
	 */
	public WallFollower(int street, int avenue, Direction direction, int beepers)
	{
		super(street, avenue, direction, beepers);

	}

	/**
	 * Create a robot on a specific street and avenue, facing a given direction with a
	 * given number of beepers and a given body color.
	 * 
	 * @param street the street on which to place the robot
	 * @param avenue the avenue on which to place the robot
	 * @param direction the direction the robot will initially face
	 * @param beepers the initial number of beepers in the beeper bag
	 * @param color the color of this robot
	 */
	public WallFollower(int street, int avenue, Direction direction, int beepers,
			Color color)
	{
		super(street, avenue, direction, beepers, color);
	}

	/**
	 * Turns this robot right.
	 */
	public void turnRight()
	{
		turnLeft();
		turnLeft();
		turnLeft();
	}

	/**
	 * Return true if there is no wall to the immediate right of this robot
	 * 
	 * @return true if the right has no wall
	 */
	public boolean rightIsClear() 
	{
		turnRight();
		if (frontIsClear())
		{
			say("Right is clear");
			turnLeft();
			return true;
		}
		turnLeft();
		return false;
	}

	/**
	 * Follow the wall to the right. Precondition. The robot must be in contact with the
	 * wall initially.
	 */
	public void followWallRight()
	{
		while (!nextToABeeper())
		{
			step();
			if (nextToABeeper())
			{
				think("Free at last.", 2);
			}
			// else if (rightIsClear()) // removed - induced too many turns
			// {
			// think("Whoa! There isn't a wall to the right any more!", 2);
			// }
		}

	}

	/**
	 * Make one step of progress toward the goal. Moving a minimal amount and turning as
	 * necessary to keep the wall to the right. Returns if a beeper is found along the
	 * way.
	 */
	public void step()
	{

		if (!this.frontIsClear())
		{
			this.turnLeft();
		} else
		{
			this.move();
			if (this.nextToABeeper())
			{
				return;
			}
			if (this.rightIsClear())
			{
				this.turnRight();
				this.move();
				if (this.nextToABeeper())
				{
					return;
				}
				if (this.rightIsClear())
				{
					this.turnRight();
					this.move();
				}
			}
		}
	}
}
