import java.awt.*;
import java.util.Iterator;

/**
 * Caterpillars, for use in the CaterpillarGame.
 *
 * @see MunchGame
 */
public class Caterpillar {

    // Private variables giving this caterpillar's characteristics
    private Color color;						// its color
    private Point position;						// the position of its head
    private int length;							// its length
    private char direction = 'E';				// the direction of its head
    private Queue body = new ArrayQueue();		// its entire body
    private int score = 0;						// its current score
    private int scoreLoc;						// x-location to print score
    private Queue commands = new ArrayQueue();	// The pending commands to be applied

    /**
     * Create a new caterpillar, with the given color and starting position
     *
     * @param c the caterpillar's color
     * @param sp the starting position
     * @param len the caterpillar's length (number of body segments)
     */
    public Caterpillar(Color c, Point sp, int len, int loc)
    {
		color = c;
		scoreLoc = loc;
		for (int i = 0; i < len; i++)
		{
		    position = new Point(sp.x + i, sp.y);
	    	body.enqueue(position);
		}
    }
	
	
    /**
     * Set the direction of the head of the caterpillar
     *
     * @param d the direction (N, S, E, or W) or stop (Z) command
     */
    public void setDirection(char d)
    {
		commands.enqueue(new Character(d));
    }
	
	
    /**
     * Get the caterpillar's score.
     *
     * @return the current score
     */
    public int score ()
    {
		return score;
    }


    /**
     * Move the caterpillar one step
     *
     * @param game the current state of the caterpillar game
     */
    public void move (MunchGame game) 
    {
		// first see if we should change direction
		if (!commands.isEmpty())
		{
		    Character c = (Character)commands.dequeue();
	    	direction = c.charValue();
	    	if (direction == 'Z') return;
		}
		// then find new position
		Point np = newPosition();
		if (game.canMove(np))
		{
		    // check if we will eat a pellet
		    if (game.pellets.inPosition(np))
		    {
				game.pellets.remove(np);
				score++;
		    }
	    // erase one segment, add another
	    body.dequeue();
	    body.enqueue(np);
	    position = np;
		}
    }


    // Calculate the next position for the caterpillar, based on its
    // current direction of movement
    private Point newPosition()
    {
		int x = position.x;
		int y = position.y;
		switch (direction)
		{
			case 'E': x++; break;
			case 'W': x--; break;
			case 'N': y--; break;
			case 'S': y++; break;
		}
		return new Point(x, y);
    }


    /**
     * Determine whether any part of the caterpillar's body lies on the
     * given position
     *
     * @param np the position to test
     * @return true if any part of the caterpillar's body lies on np
     */
    public boolean inPosition(Point np)
    {
		Iterator i = ((ArrayQueue)body).iterator();
		while (i.hasNext())
		{
			Point location = (Point)i.next();
			if (np.equals(location))
				return true;
		}
		return false;
    }
	
	
    /**
     * Draw the caterpillar on the given graphics pane
     *
     * @param g the graphics pane on which to draw the caterpillar
     */
    public void paint(Graphics g)
    {
		g.setColor(color);
		Iterator i = ((ArrayQueue)body).iterator();
		while (i.hasNext())
		{
		    Point p = (Point) i.next();
	 		g.fillOval(5 + MunchGame.SegmentSize * p.x,
	 				   15 + MunchGame.SegmentSize * p.y,
	 				   MunchGame.SegmentSize, MunchGame.SegmentSize);
		}
		g.drawString(Integer.toString(score), scoreLoc,
					 MunchGame.SegmentSize *(MunchGame.BoardHeight+2));
    }
}
