package edu.unl.consystlab.sudokuSolver.consistencyAlgorithms;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

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

public class shavingSingleMAC extends consistencyAlgorithm {

	arcConsistency myArcConsistency;
	problemVariable myVariable;
	
	public shavingSingleMAC(constraintProblem newProblem, sudokuBoard board, problemVariable newVariable)
	{
		super(newProblem, board);
		myArcConsistency = new arcConsistency(newProblem, board);
		brokenConstraint = null;
		setEncounteredError(false);
		myVariable = newVariable;
	}
	
	//always returns true because it never breaks a constraint
	public boolean runAlgorithm()
	{
		//collect every variable
		// take a variable
		// assign it a value
		// run mac, if there is no error leave the value
		// if there is an error remove the value
		// move to the next value
		// move to the next variable
		variableReductions = new LinkedList();

		//if it is assigned then there is no shaving to do
		if(!myVariable.isAssigned())
		{
			List originalDomain = new LinkedList(myVariable.getEntireDomain());
			Iterator j = originalDomain.iterator();
			while(j.hasNext())
			{
				String currentValue = (String)j.next();
				List tempDomain = new LinkedList(myVariable.getEntireDomain());
				
				//assign the variable some value
				myVariable.setAssigned(currentValue);
				//run MAC
				if(!myArcConsistency.runAlgorithm())
				{
					//remove it from the domain
					tempDomain.remove(currentValue);
					//keep track of all the values removed here because we can't trust the problem itself
					// since arc consistency removes a lot of variables that come back
					variableIndexAndValueGrouping myReduction = new variableIndexAndValueGrouping(myVariable.getIndex(), currentValue);
					variableReductions.add(myReduction);
				}
				
				//undo Assignment
				myVariable.unSetAssigned();
				myVariable.setCurrentDomain(tempDomain);
				
				
				//undo the MAC
				Iterator k = myArcConsistency.getVariableReductions().iterator();
				while(k.hasNext())
				{
					variableIndexAndValueGrouping currentReduction = (variableIndexAndValueGrouping)k.next();
					parentProblem.getVariable(currentReduction.getVariableIndex()).addToCurrentDomain(currentReduction.getValue());
				}
				
				//check to see if a variable's domain is squashed.
				if(tempDomain.size() == 0)
				{
					//just pick the first arc consistent constraint to make broken
					brokenConstraint = (problemConstraint)myVariable.getBinaryConstraints().get(0);
					setEncounteredError(true);
					return false;								
				}

			}
		}
		
		return true;
	}
}
