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

import edu.unl.consystlab.sudokuSolver.constraintProblem;
import edu.unl.consystlab.sudokuSolver.problemConstraint;
import edu.unl.consystlab.sudokuSolver.problemVariable;
import edu.unl.consystlab.sudokuSolver.sudokuBoard;

public class arcConsistency extends consistencyAlgorithm {

	public arcConsistency(constraintProblem newProblem, sudokuBoard board) {
		super(newProblem, board);
	}
	
	//returns true if it doesn't hit an error,
	//returns false if it does encounter an error
	public boolean runAlgorithm()
	{
		variableReductions = new LinkedList();
		parentProblem.registerDomainReductionListener(variableReductions);
		
		Stack constraintQueue = new Stack();
		//fill it with all the constraints first
		constraintQueue.addAll(parentProblem.getAllConstraints());
		
		problemConstraint currentConstraint;
		while(constraintQueue.size() > 0)
		{
			currentConstraint = (problemConstraint)constraintQueue.pop();
			if(!currentConstraint.isViolated())
			{
				if(  currentConstraint.revise( (problemVariable)(currentConstraint.getScope()).get(0) )  )
				{
					List constraintList = new LinkedList();
					constraintList = 
						((problemVariable)(currentConstraint.getScope()).get(0)).getBinaryConstraints();
					for(int i = constraintList.size(); i > 0; i--)
					{
						constraintQueue.add(constraintList.get(i-1));
					}
				}
				if(  currentConstraint.revise( (problemVariable)(currentConstraint.getScope()).get(1) )  )
				{
					List constraintList = new LinkedList();
					constraintList = 
						((problemVariable)(currentConstraint.getScope()).get(1)).getBinaryConstraints();
					for(int i = constraintList.size(); i > 0; i--)
					{
						constraintQueue.add(constraintList.get(i-1));
					}
				}
			}
			else
			{
				//we have hit an error return
				parentProblem.unregisterDomainReductionList(variableReductions);
				setBrokenConstraint(currentConstraint);
				setEncounteredError(true);
				return false;
			}
		}
		parentProblem.unregisterDomainReductionList(variableReductions);
		setBrokenConstraint(null);
		setEncounteredError(false);
		return true;
	}
}
