package cz.cuni.amis.utils.astar;

import java.util.Collection;

/**
 * This class defines the goal of A* algorithm, it affects how the A* works.
 * When implementing this class you may a few several things.
 * <p><p>
 * 1) extra cost for edges between two nodes
 * 2) wether A* may use the node (this is useful when you want to forbig some nodes / states)
 * 3) heuristic function which estimates the distance from node to the goal node
 * <p><p>
 *    !NOTE!
 * <p><p>   
 *    That this heuristic must be correct for A* to work correctly, that means
 *    the returned distance must be smaller or equal to the real distance.
 *    (In 2D, 3D a euclidian metric will do the job).
 * <p><p>   
 * Open and Close list will also be stored in this class - that's because after the
 * A* finish the job you might be interested what's inside them.
 * <p><p>
 * When you providing a AStarGoal to a AStar.aStar() be sure that AStarOpenList and
 * AStarCloseList is empty!
 */
public interface AStarGoal<NODE> {
	
	/**
	 * This is called at the beggining of the A* algorithm to bind the open list
	 * to the goal (you may use it check which nodes we've visited, etc... for
	 * extra cost for instance). DON'T CHANGE IT!
	 */
	public void setOpenList(Collection<NODE> openList);
	
	/**
	 * This is called at the beggining of the A* algorithm to bind the close list
	 * to the goal (you may use it check which nodes we've visited, etc... for
	 * extra cost for instance). DON'T CHANGE IT!
	 */
	public void setCloseList(Collection<NODE> closeList);
	
	/**
	 * This is heuristic function.
	 * 
	 * !NOTE!
	 *    
	 * That this heuristic must be correct for A* to work correctly, that means
	 * the returned distance must be smaller or equal to the real distance.
	 * (In 2D, 3D a euklidian metric will do the job).
	 * 
	 * @return how far is to the goal from the node
	 */
	 public int getEstimatedDistanceToGoal(NODE node);

	 /**
	  * Returns true if A* can use this node (e.g. to step on this type of floor)
      * You can use it to forbid some specific nodes	  
	  */
	 public boolean isNodeOpened(NODE node); 

	 /**
	  * Returns extra cost to add to value when trying to go
      * nodeFrom to nodeTo ... of course it can depends only on nodeTo 
      * (some special kind of a floor for instance)
      * 
      * Don't worry about the edge cost to become negative, A* ensures that
      * that the least cost is 0 (Algorithm can't work over graphs with negative
      * costs.)
      * 
	  * @return extra cost of edge for nodeFrom -> nodeTo
	  */
	 public int getExtraCost(NODE nodeFrom, NODE nodeTo);
	 
	 /**
	  * Returns true, if we've reached the goal ... e.g. actualNode
      * is node we were trying to get to
      * if this function never returns true, A* will run until
      * all nodes are evaluated
	  * @param actualNode
	  */
	 public boolean isGoalReached(NODE actualNode);
}
