package edu.calpoly.csc480.Corral.Agent.Util;

import java.awt.*;

import edu.calpoly.csc480.Corral.Agent.*;
import edu.calpoly.csc480.Corral.Agent.InformedAgent.*;
import edu.calpoly.csc480.Corral.Agent.UninformedAgent.*;
import edu.calpoly.csc480.Corral.Seer.*;
import edu.calpoly.csc480.Corral.Tile.*;
import edu.calpoly.csc480.Corral.Tile.PlotTile.*;

public class NodeCallback extends BaseCallback {
	public NodeCallback(BaseSeer seer) {
		super(seer);
		tiles = seer.getArea().getTiles().getTiles();
		rules = seer.getRules();
		means = (Means)seer.getArea().getMeans();

		isGreedyAgent = (means.getAgent() instanceof GreedyAgent);
		isStarAgent   = (means.getAgent() instanceof StarAgent);

		if (isGreedyAgent || isStarAgent) {
			informedMeans = (InformedMeans)means;
		}
	}

	public void setCost(Node node) {
		GreedyAgent.GreedyNode greedyNode;
		StarAgent.StarNode starNode;

		DirtTile dirt;
		BaseTile tile;
		Point point;

		if (node.type == Node.moveType) {
			point = node.state.location;
			tile = tiles[point.y][point.x];

			if (tile instanceof WallTile) {
				node.state.location = node.parentState.location;
			}
			else {
				node.pathCost += rules.moveCost;

				if (tile instanceof DirtTile) {
					dirt = (DirtTile)tiles[point.y][point.x];
					node.pathCost += dirt.getCost();
					dirt.clean();
				}
				else if (tile instanceof GoalTile) {
					seer.over();
				}
			}
		}
		else {
			node.pathCost += rules.turnCost;
		}

		if (isGreedyAgent) {
			greedyNode = (GreedyAgent.GreedyNode)node;
			informedMeans.setGuessCost(greedyNode.guessCost);
		}
		else if (isStarAgent) {
			starNode = (StarAgent.StarNode)node;
			starNode.totalCost = (short)(starNode.pathCost + starNode.guessCost);
			informedMeans.setGuessCost(starNode.guessCost);
			informedMeans.setTotalCost(starNode.totalCost);
		}
	}
	
	public void perform(Node node) {
		means.setPathCost(node.pathCost);
		means.setTeleportation(node.state.location);
		
		if (node.type == Node.turnType) {
			means.setDirection(node.state.direction);
		}
		else {
			means.setLocation(node.state.location);
		}
	}

	public void reset() {
		means.getOwner().getOwner().initBeans();
	}

	protected BaseTile[][] tiles;
	protected BaseRules rules;
	protected Means means;

	protected boolean isGreedyAgent, isStarAgent;
	protected InformedMeans informedMeans;	
}