package edu.calpoly.csc480.Corral.Agent;

import java.awt.*;

import com.bcurry.www.awt.*;

import edu.calpoly.csc480.Corral.Agent.Util.*;
import edu.calpoly.csc480.Corral.Tile.*;

abstract public class Agent extends BaseAgent implements
 TileReceiver, LifeReceiver,
 NodeProducer
{
	public Agent() {
	}
	
	public void setCallback(NodeCallback nodeCB) {
		this.nodeCB = nodeCB;
	}
	
	public void receive(BaseTile tile, State state) {
		Node node;

		chart = new Chart();
		queue = makeQueue();
		node = getFirstNode();
		node.state = state;

		chart.add(tile);
		chart.setMovedTo (node.state.location);
		chart.setTurnedTo(node.state.location);
		chart.setTurnedTo(
		 BasicPoint.add(node.state.location, state.direction.getPoint()));
	}

	public void receive(BaseTile tile) {
		Node node;

		chart.add(tile);
		expand(node = queue.pop());
		nodeCB.perform(node);
	}
	
	protected NodeCallback nodeCB;

	protected Queue queue;
	protected Chart chart;

	protected BaseAgentView makeView()		{return new AgentView();}

	protected void expand(Node parent) {
		int drift;
		Node child;
		Point chartPoint;
		BaseTile tile;

		for (drift = 0; drift < Direction.numDirections; drift++) {
			chartPoint =
			 BasicPoint.add(parent.state.location, Direction.points[drift]);

			if (!chart.haveTurnedTo(chartPoint)) {
				chart.setTurnedTo(chartPoint);

				child = queue.make(parent);
				child.state.location  = parent.state.location;
				child.state.direction = Direction.directions[drift];
				child.type = Node.turnType;
				nodeCB.setCost(child);
				queue.push(child);
			}
		
			tile = chart.get(chartPoint);
		
			if (!chart.haveMovedTo(chartPoint) &&
			 tile != null && !(tile instanceof WallTile)) {
				chart.setMovedTo(chartPoint);
				chart.setTurnedTo(chartPoint);

				child = queue.make(parent);
				child.state.location  = new Point(chartPoint);
				child.state.direction = Direction.directions[drift];
				child.type = Node.moveType;
				nodeCB.setCost(child);
				queue.push(child);
			}
		}
	}

	protected Node getFirstNode() {
		return queue.peek();
	}
	
	protected Queue makeQueue()	{return null;}
}