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 shavingMAC extends consistencyAlgorithm {

	arcConsistency myArcConsistency;
	
	public shavingMAC(constraintProblem newProblem, sudokuBoard board)
	{
		super(newProblem, board);
		myArcConsistency = new arcConsistency(newProblem, board);
		brokenConstraint = null;
		setEncounteredError(false);
	}
	
	//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();
		boolean runAgain = true;
		
		while(runAgain != false)
		{
			runAgain = false;
			Iterator i = ((Collection)parentProblem.getAllVariables()).iterator();
			//go through all varialbes
			while(i.hasNext())
			{
				problemVariable currentVariable = (problemVariable)i.next();
				//if it is assigned then there is no shaving to do
				if(!currentVariable.isAssigned())
				{
					List originalDomain = new LinkedList(currentVariable.getEntireDomain());
					Iterator j = originalDomain.iterator();
					while(j.hasNext())
					{
						String currentValue = (String)j.next();
						List tempDomain = new LinkedList(currentVariable.getEntireDomain());
						
						//assign the variable some value
						currentVariable.setAssigned(currentValue);
						//run MAC
						if(!myArcConsistency.runAlgorithm())
						{
							//remove it from the domain
							tempDomain.remove(currentValue);
							runAgain = true;
							//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(currentVariable.getIndex(), currentValue);
							variableReductions.add(myReduction);
						}
						
						//undo Assignment
						currentVariable.unSetAssigned();
						currentVariable.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)currentVariable.getBinaryConstraints().get(0);
							setEncounteredError(true);
							return false;								
						}
	
					}
				}
			}
		}
		
		return true;
	}
}
