package edu.umich.soar.hpp;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Somewhat efficient support for a set of multi-valued variables
 */
public class HPPKnowledgeBase {
	
	/**
	 * Append a variable to the KB
	 * 
	 * @param varName variable name
	 * @param varValue variable value
	 */
	public void addVariable(String varName, String varValue) {
		if (!myKB.containsKey(varName)) {
			myKB.put(varName, new LinkedList<HPPGivenVariable>());
		}
		
		myKB.get(varName).add(new HPPGivenVariable(varName, varValue));
	}
		
	/**
	 * Supports read-only access to all the values of a variable
	 * 
	 * @param varName variable name
	 * @return iterator to variable value(s), or null if KB does not contain the variable
	 */
	public Iterator<HPPGivenVariable> getVariableValues(String varName) {
		if (!containsVariable(varName)) {
			return null;
		}
		
		return myKB.get(varName).iterator();
	}
	
	/**
	 * Supports read-only access to all variable names
	 * 
	 * @return the set of variable names
	 */
	public Set<String> getVariables() {
		return myKB.keySet();
	}
	
	/**
	 * Supports search by variable name
	 * 
	 * @param varName variable name
	 * @return returns true if the KB has at least one value for the variable
	 */
	public boolean containsVariable(String varName) {
		return myKB.containsKey(varName);
	}
	
	/**
	 * Supports search by variable name+value
	 * 
	 * @param varName variable name
	 * @param varValue variable value
	 * @return returns true if the KB has the precise variable name+value pair
	 */
	public boolean containsVariableValue(String varName, String varValue) {
		if (!containsVariable(varName)) {
			return false;
		}
		
		Iterator<HPPGivenVariable> vit = getVariableValues(varName);
		if (vit!=null) {
			while (vit.hasNext()) {
				HPPGivenVariable v = (HPPGivenVariable) vit.next();
				
				if (varValue.compareTo(v.getValue())==0) {
					return true;
				}
			}
		}
		
		return false;
	}
	
	/**
	 * Basic empty-KB constructor
	 */
	public HPPKnowledgeBase() {
		myKB = new HashMap<String, List<HPPGivenVariable>>();
	}
	
	private final Map<String, List<HPPGivenVariable>> myKB;
}
