// ---------------------------------------------
// Javascript routines to validate sudoku forms
//
// function IsValid()			- Function called by onchange in text box to check that a 1-9 is entered
// function FixForm				- Function to fix cells
// function ClearForm(stat)		- Function to clear sudoku or reset back to start - parameters 1=reset 0=clear
// function ValidateForm()		- Function to validate boxes/rows/columns
// function ValidateBox()		- Function called by ValidateForm, validates all boxes
// function ValidateRow()		- Function called by ValidateForm, validates all rows
// function ValidateColumn()	- Function called by ValidateForm, validates all columns
// function NextMove()			- Function to show next available move
// function NextMoveCheckCell	- Function called from NextMove checks cell for only one option - parameters boxNo cellNo
// function NextMoveCheckBox	- Function called from NextMove checks cell if a number can only go in there once - parameters number boxNo
// var proceed					- Global variable to determine whether or not to contiue validating
// var emptyCells				- Global variable to determine if sudoku is complete
// var bgEmpty					- Global variable to set bgColor of empty cells
// var byError					- Global variable to set bgColor of errors
// var bgFixed					- Global variable to set bgColor of fixed cells
// var bgFixedError				- Global variable to set bgColor of fixed cells which cause errors
// var bgHelp					- Global variable to set bgColor of cells where help has been provided
// ---------------------------------------------

var proceed = 2;
var emptyCells = false;
var bgEmpty = '#ffffff';
var bgError = '#ff0000';
var bgFixed = '#e5e5e5';
var bgFixedError ='#33cc00'
var bgHelp = '#fff000';

function IsValid(obj)
{
	var validText = /^[1-9]{1,1}$/;
	if (!validText.test(obj.value)) obj.value = "";
}

function FixForm()
{
	for (i=1;i<10;i++)
	{
		for (j=1;j<10;j++)
		{
			if (document.getElementById('txtB'+i+'C'+j).value!="")
			{
				document.getElementById('B'+i+'C'+j).bgColor=bgFixed;
			}
			else
			{
				document.getElementById('B'+i+'C'+j).bgColor=bgEmpty;
			}
		}
	}
}

function IsFixed(boxNo, cellNo)
{
	// We no it is fixed by the bgColor
}

function ClearForm(stat)
{
	if(stat==1) //Reset
	{
		for (i=1;i<10;i++)
		{
			for (j=1;j<10;j++)
			{
				if (document.getElementById('B'+i+'C'+j).bgColor==bgFixed || document.getElementById('B'+i+'C'+j).bgColor==bgFixedError )
				{
					document.getElementById('B'+i+'C'+j).bgColor=bgFixed;
				}
				else
				{
					document.getElementById('txtB'+i+'C'+j).value = "";
					document.getElementById('B'+i+'C'+j).bgColor=bgEmpty;
				}
			}
		}
	}
	else if(stat==0) //Clear
	{
		for (i=1;i<10;i++)
		{
			for (j=1;j<10;j++)
			{
				document.getElementById('txtB'+i+'C'+j).value = "";
				document.getElementById('txtB'+i+'C'+j).name = 'txtB'+i+'C'+j;
				document.getElementById('B'+i+'C'+j).bgColor=bgEmpty;
			}
		}
	}
}

function ValidateForm()
{
	// This is the routine which will validate the form
	//First thing to do is undo the bgColor in previous checks
	for (i=1;i<10;i++)
	{
		for (j=1;j<10;j++)
		{
			if (document.getElementById('B'+i+'C'+j).bgColor==bgFixed || document.getElementById('B'+i+'C'+j).bgColor==bgFixedError)
			{
				document.getElementById('B'+i+'C'+j).bgColor=bgFixed;
			}
			else
			{
				document.getElementById('B'+i+'C'+j).bgColor=bgEmpty;
			}
		}
	}
	var stat	
	//We need to check Boxes, rows & Columns
	stat = ValidateBox()
	if (stat != proceed) return;
	stat = ValidateRow()
	if (stat != proceed) return;
	stat = ValidateColumn()
	if (stat != proceed) return;
	
	//If no empty cells found and validation has passed then we are done...
	if (!emptyCells) alert("Congratulations - Sudoku compelte");
}

function ValidateBox()
{
	emptyCells=false;
	//Boxes are numbered BnCn so we check B1C1-B1C9, B2C1-B2C9 etc
	for (i=1;i<10;i++)
	{
		checkArray=new Array(0,0,0,0,0,0,0,0,0);
		for (j=1;j<10;j++)
		{
			cellValue=document.getElementById('txtB'+i+'C'+j).value; //get the input box
			if (cellValue!="") // ignore empty cells
			{
				if (checkArray[cellValue-1]==0) //We haven't hit this before
				{
					checkArray[cellValue-1]=cellValue; //Store it in the array
				}
				else
				{
					alert('Box '+i+' has duplicates');
					for (k=1;k<10;k++)
					{
						if ((document.getElementById('txtB'+i+'C'+k).value)==cellValue)
						{
							if (document.getElementById('B'+i+'C'+k).bgColor==bgFixed)
							{
								document.getElementById('B'+i+'C'+k).bgColor=bgFixedError;
							}
							else
							{
								document.getElementById('B'+i+'C'+k).bgColor=bgError; //Change Cells Red
							}
						}
					}
					return false; // If we don't return and we have multiple errors it could be confusing
				}
			}
			else emptyCells=true;
		}
	}
	return proceed;
}

function ValidateRow()
{
//The first row is B1C1, B1C2, B1C3, B2C1, B2C2, B2C3, B3C1, B3C2, B3C3 etc, so we need to calculate reference
	for (i=1;i<10;i++)
	{
		checkArray=new Array(0,0,0,0,0,0,0,0,0);
		for (j=1;j<10;j++)
		{
			boxNo=(Math.floor((i-1)/3)*3)+Math.floor((j-1)/3)+1;
			cellNo=((i-1)%3)*3+((j-1)%3)+1;
			cellValue=document.getElementById('txtB'+boxNo+'C'+cellNo).value; //get the input box
			if (cellValue!="") // ignore empty cells
			{
				if (checkArray[cellValue-1]==0) //We haven't hit this before
				{
					checkArray[cellValue-1]=cellValue; //Store it in the array
				}
				else
				{
					alert('Row '+i+' has duplicates');
					for (k=1;k<10;k++)
					{
						//we need to recalculate the row and column numbers for this row
						boxNoRed=(Math.floor((i-1)/3)*3)+Math.floor((k-1)/3)+1;
						cellNoRed=((i-1)%3)*3+((k-1)%3)+1;
						if ((document.getElementById('txtB'+boxNoRed+'C'+cellNoRed).value)==cellValue)
						{
							if (document.getElementById('B'+boxNoRed+'C'+cellNoRed).bgColor==bgFixed)
							{
								document.getElementById('B'+boxNoRed+'C'+cellNoRed).bgColor=bgFixedError; 
							}
							else
							{
								document.getElementById('B'+boxNoRed+'C'+cellNoRed).bgColor=bgError; //Change Cells Red
							}
						}
					}
					return false; // If we don't return and we have multiple errors it could be confusing
				}
			}
		}
	}
	return proceed;
}

function ValidateColumn()
{
//The first column is B1C1, B1C4, B1C7, B4C1, B4C4, B4C7, B7C1, B7C4, B7C7 etc, so we need to calculate reference
	for (i=1;i<10;i++)
	{
		checkArray=new Array(0,0,0,0,0,0,0,0,0);
		for (j=1;j<10;j++)
		{
			boxNo=(Math.floor((j-1)/3)*3)+Math.floor((i-1)/3)+1;
			cellNo=((j-1)%3)*3+((i-1)%3)+1;
			cellValue=document.getElementById('txtB'+boxNo+'C'+cellNo).value; //get the input box
			if (cellValue!="") // ignore empty cells
			{
				if (checkArray[cellValue-1]==0) //We haven't hit this before
				{
					checkArray[cellValue-1]=cellValue; //Store it in the array
				}
				else
				{
					alert('Column '+i+' has duplicates');
					for (k=1;k<10;k++)
					{
						//we need to recalculate the row and column numbers for this row
						boxNoRed=(Math.floor((k-1)/3)*3)+Math.floor((i-1)/3)+1;
						cellNoRed=((k-1)%3)*3+((i-1)%3)+1;
						if ((document.getElementById('txtB'+boxNoRed+'C'+cellNoRed).value)==cellValue)
						{
							if (document.getElementById('B'+boxNoRed+'C'+cellNoRed).bgColor==bgFixed)
							{
								document.getElementById('B'+boxNoRed+'C'+cellNoRed).bgColor=bgFixedError;
							}
							else
							{
								document.getElementById('B'+boxNoRed+'C'+cellNoRed).bgColor=bgError; //Change Cells Red
							}
						}
					}
					return false; // If we don't return and we have multiple errors it could be confusing
				}
			}
		}
	}
	return proceed;
}

function NextMove()
{
// Okay there are several ways forward.
// We want to See if there is only 1 place a value will fit in a box, a row or a column
// Next see if there is only 1 option eg cell can't be 1,2,3,4,5,6,7,8 so must be 9
// 
// IDEAS - I guess we want to take each cell and see what numbers it can be

	var stat	

	//First off Let us check for only option
	for (x=1;x<10;x++)
	{
		for (y=1;y<10;y++)
		{
			cellValue=document.getElementById('txtB'+x+'C'+y).value;
			if (cellValue=="") 
			{
				stat=NextMoveCheckCell(x,y);
				if (stat != proceed) return				
			}
		}
	}
	
	for (x=1;x<10;x++) //look at each number in turn
	{
		for (y=1;y<10;y++) //and then go for each box
		{
			stat=NextMoveCheckBox(x,y);
			if (stat != proceed) return								
		}
	}
}

function NextMoveCheckCell(boxNo, cellNo)
{
	arrayNumbers=new Array(0,0,0,0,0,0,0,0,0); // We have a new cell so reset the array

	for (i=1;i<10;i++) //Set up array with all the values currently in the box
	{
		cellValue=document.getElementById('txtB'+boxNo+'C'+i).value;
		if (cellValue!="") arrayNumbers[cellValue-1]=cellValue;
	}

	rowNo=(Math.floor((boxNo-1)/3)*3)+Math.floor((cellNo-1)/3)+1; //We need this to work out which row we are crossing
	for (i=1;i<10;i++)//No work across the row and add the values to the array
	{
		rowBoxNo=(Math.floor((rowNo-1)/3)*3)+Math.floor((i-1)/3)+1;
		rowCellNo=((rowNo-1)%3)*3+((i-1)%3)+1;
		cellValue=document.getElementById('txtB'+rowBoxNo+'C'+rowCellNo).value;
		if (cellValue!="") arrayNumbers[cellValue-1]=cellValue;
	}

	colNo=((boxNo-1)%3)*3+((cellNo-1)%3)+1; //We need this to work out which column we are crossing
	for (i=1;i<10;i++)//No work down the row and add the values to the array
	{
		colBoxNo=(Math.floor((i-1)/3)*3)+Math.floor((colNo-1)/3)+1;
		colCellNo=((i-1)%3)*3+((colNo-1)%3)+1;
		cellValue=document.getElementById('txtB'+colBoxNo+'C'+colCellNo).value;
		if (cellValue!="") arrayNumbers[cellValue-1]=cellValue;
	}
	
	//We now have an array of numbers let us count the 0's
	var missingNumber = 0;
	for (i=1;i<10;i++)
	{
		if (arrayNumbers[i-1]==0)
		{
			if (missingNumber==0) // We haven't yet encountered a number so store i
			{
				missingNumber=i;
			}
			else // We have more than 1 missing number in this square so return
			{
				return proceed;
			}
		}
	}
	
	if (missingNumber!=0)
	{
		document.getElementById('txtB'+boxNo+'C'+cellNo).value=missingNumber;
		document.getElementById('B'+boxNo+'C'+cellNo).bgColor=bgHelp;
		return false;
	}
}

function NextMoveCheckBox(iNo, boxNo)
{
	for (i=1;i<10;i++) // loop through every cell in the box
	{
		cellValue=document.getElementById('txtB'+boxNo+'C'+i).value; //get the input box
		if (cellValue==iNo) // we have this number in the box
		{
			return proceed;
		}
	}
	
	var cellFound = "";
	// We want to try and place iNo in each cell in the square
	for (cellNo=1;cellNo<10;cellNo++)
	{
		cellValue=document.getElementById('txtB'+boxNo+'C'+cellNo).value; //get the input box
		if (cellValue=="")// we have a non blank square
		{
			var iNoFound = false;
			rowNo=(Math.floor((boxNo-1)/3)*3)+Math.floor((cellNo-1)/3)+1; //We need this to work out which row we are crossing
			for (i=1;i<10;i++) //Let us see if that value exists anywhere in the row yet
			{
				rowBoxNo=(Math.floor((rowNo-1)/3)*3)+Math.floor((i-1)/3)+1;
				rowCellNo=((rowNo-1)%3)*3+((i-1)%3)+1;
				cellValue=document.getElementById('txtB'+rowBoxNo+'C'+rowCellNo).value;
				if (cellValue==iNo) iNoFound=true;
			}
			if (!iNoFound) //If number is found in row there is no point checking the column
			{
				colNo=((boxNo-1)%3)*3+((cellNo-1)%3)+1; //We need this to work out which column we are crossing
				for (i=1;i<10;i++)//Now work down the column and add the values to the array
				{
					colBoxNo=(Math.floor((i-1)/3)*3)+Math.floor((colNo-1)/3)+1;
					colCellNo=((i-1)%3)*3+((colNo-1)%3)+1;
					cellValue=document.getElementById('txtB'+colBoxNo+'C'+colCellNo).value;
					if (cellValue==iNo)  iNoFound=true;
				}				
			}
			if (!iNoFound) // The number hasn't been found so it can be placed here
			{
				if (cellFound=="") // We haven't yet placed a number here
				{
					cellFound = 'B'+boxNo+'C'+cellNo;
				}
				else // We have found somewhere else to place a number so stop looking
				{
					cellFound=="";
					return proceed;
				}
			}
		}
	}
	
	// so we have looped through all avaliable cells in this box, so let us see we have a value in cellFound
	if (cellFound!="")
	{
		document.getElementById('txt'+cellFound).value=iNo;
		document.getElementById(cellFound).bgColor=bgHelp;
		return false;
	}
	else
	{
		return proceed;
	}
}