package edu.unl.consystlab.sudokuSolver;
import java.util.List;
import java.util.LinkedList;

public abstract class problemConstraint
{

	protected constraintProblem parentProblem;
	protected List constraintScope;
	//protected constraintRelation constraintConflictsRelation;

	public problemConstraint(String constraintScopeString, constraintProblem currentProblem)
	{
		parentProblem = currentProblem;
		//constraintScope = new LinkedList();
		constraintScope = parseScope(constraintScopeString);

		/*handle these at a lower level
		//currentProblem.addConstraint(this, constraintScope);

		//tell the variables in the scope about this constraint
		for(int i=0; i<constraintScope.size(); i++)
		{
			((problemVariable)constraintScope.get(i)).addBinaryConstraint(this);
		}
		*/

	}

//	public void setRelation(String newRelation)
//	{
//		constraintConflictsRelation= parentProblem.getRelation(newRelation);
//		return;
//	}
	
	public List getScope()
	{
		return constraintScope;
	}
	
	public boolean revise( problemVariable reviseVariable)
	{
		//we are going to cheat... since we know it will only be inconsistant if the domain
		//of the variable not being revised is only one we check to see if it is one.  If it
		//has just one variable then there may be some arc consistency to enforce.
		
		//figure out which in the scope we are dealing with
		if( (((problemVariable)constraintScope.get(0)).getIndex().compareTo(reviseVariable.getIndex()))== 0 )
		{
			//the one we look at is index 1
			if ( ((problemVariable)constraintScope.get(1)).getCurrentDomainSize() == 1 )
			{	//we now have the potential for revising
				String theValue = ((problemVariable)constraintScope.get(1)).getCurrentDomainFirstValue();
				if(reviseVariable.isInCurrentDomain(theValue))
				{
					//remove the value and return true
					reviseVariable.removeFromCurrentDomain(theValue);
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{ //no revising will take place.
				return false;
			}
		}
		else
		{
			//the one we look at is index 0
			if ( ((problemVariable)constraintScope.get(0)).getCurrentDomainSize() == 1 )
			{	//we now have the potential for revising
				String theValue = ((problemVariable)constraintScope.get(0)).getCurrentDomainFirstValue();
				if(reviseVariable.isInCurrentDomain(theValue))
				{
					//remove the value and return true
					reviseVariable.removeFromCurrentDomain(theValue);
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{ //no revising will take place.
				return false;
			}
		}
	}
	//	public int arity()
//	{
//		//may or may not work
//		int numVariables = 0;
//		numVariables = constraintScope.size();
//		return numVariables;
//	}

	
	public List parseScope(String constraintScopeString)
	{
		String[] scopes = null;
		scopes = constraintScopeString.split(" ");
		List myConstraintScopeList = new LinkedList();
		for(int i=0; i < scopes.length; i++)
		{
			myConstraintScopeList.add( parentProblem.getVariable(scopes[i]) );
			//parentProblem.getVariable(scopes[i]).addConstraint(this);
		}
		return(myConstraintScopeList);

	}
	
	public abstract boolean isViolated();
}