package edu.umich.soar.hpp;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * A plan action that supports arbitrary hierarchy via sub-plans
 * and conditionality based upon a conjunctive set of variable name/value pairs.
 */
public class HPPAction {	
	
	/**
	 * Supports read-only access to the action name
	 * 
	 * @return action name
	 */
	public String getName() {
		return myName;
	}
	
	/**
	 * Supports read-only access to the sub-plan
	 * 
	 * @return sub-plan (or null if none)
	 */
	public HPPlan getSubPlan() {
		return mySubPlan;
	}
	
	/**
	 * Supports read-only access to condition set
	 * 
	 * @return iterator to constraint set
	 */
	public Iterator<HPPConstraint> getConditions() {
		return myConditions.iterator();
	}
	
	/**
	 * Support appending to the condition set
	 * 
	 * @param newConstraint condition to add
	 */
	public void addCondition(HPPConstraint newConstraint) {
		myConditions.add(newConstraint);
	}
	
	/**
	 * Evaluates satisfaction of the action relative to a supplied knowledge base
	 * 
	 * @param kb set of variable name/value pairs
	 * @return true if action conditions are satisfied by the supplied kb
	 */
	public boolean isSatisfied(HPPKnowledgeBase kb) {
		boolean retValue = true;
		
		Iterator<HPPConstraint> it = getConditions();
		while (retValue && it.hasNext()) {
			HPPConstraint c = (HPPConstraint) it.next();			
			retValue = kb.containsVariableValue(c.getName(), c.getValue());
		}
		
		return retValue;
	}
	
	/**
	 * Basic constructor - initializes to empty condition set
	 * 
	 * @param name action name
	 * @param subPlan action sub-plan (or null if none)
	 */
	public HPPAction(String name, HPPlan subPlan) {
		myName = name;
		mySubPlan = subPlan;
		
		myConditions = new HashSet<HPPConstraint>();
	}	
	
	/**
	 * Advanced constructor - supports custom initial condition set via array
	 * 
	 * @param name action name
	 * @param conditions action sub-plan
	 * @param subPlan initial condition set
	 */
	public HPPAction(String name, HPPConstraint[] conditions, HPPlan subPlan) {
		this(name, subPlan);
		
		for (HPPConstraint c : conditions) {
			addCondition(c);
		}
	}
	
	private final String myName;
	private final Set<HPPConstraint> myConditions;
	private final HPPlan mySubPlan;
}
