/**
 * @author Andrew Stuart
 */

var clear_results;
function bit_count( b ){
    var n=0;
	if (!b) {
		return 0;
	}
    do { ++n; } while ( (b &= (b-1)) );
    return n;
}
function IsNumeric(strChar) {  //  check for valid numeric strings
	var strValidChars="123456789";
	var blnResult=true;

	if (strChar.length === 0) {
		return false;
	}

	if (strValidChars.indexOf(strChar) == -1) {
		blnResult = false;
	}
	return blnResult;
}
function IsNumeric2(strChar) {  //  check for valid numeric strings
	var strValidChars="0123456789";
	var blnResult=true;

	if (strChar.length === 0) {
		return false;
	}
	var n = parseInt(strChar);
	if( isNaN(n) ) { return false;}
	if (n<1 || n>45) { return false;}
	return true;
}
function IsNumericKenKen(strChar) {  //  check for valid numeric strings
	var strValidChars="0123456789+-x/";
	var blnResult=true;

	if (strChar.length === 0) {
		return false;
	}
	var n = parseInt(strChar);
	if( isNaN(n) ) { return false;}
	if (n<1) { return false;}
	return true;
}

function mask2str( m ) {
	var i,p=0,str='';
	for (i = 0; i < 9; i++) {
		if (m & (1 << i)) {
			if (p++) {
				str = str + '/';
			}
			str = str + abetx.charAt(i);
		}
	}
	return str;
}
function bit2int( m ) {
	switch( m ) {
	case 1   : return 0;
	case 2   : return 1;
	case 4   : return 2;
	case 8   : return 3;
	case 16  : return 4;
	case 32  : return 5;
	case 64  : return 6;
	case 128 : return 7;
	case 256 : return 8;
	}
	return 0;
}
function cordit(y,x){
	if (coordmode === 0) {
		return 'r' + abetx.charAt(y) + 'c' + abetx.charAt(x);
	}
	return abety.charAt(y) + abetx.charAt(x);
}
function strat_add( s ) {
	var doc;
	if (!document.ifrm) {
		doc = document.getElementById("ifrm").contentDocument;
	}
	else {
		doc = document.ifrm.document;
	}
	if( clear_results ) { // clear anything from server
		doc.body.innerHTML = s;
		clear_results = false;
	} else {
		doc.body.innerHTML = doc.body.innerHTML + s;
	}
}
function change_hints(){
	showhints=!showhints;
	for (var j = 0; j < 9; j++) {
		for (var i = 0; i < 9; i++) {
			if (g[j][i] === 0) {
				lable_square(j, i, 0);
			}
		}
	}
}
function convert_str2mask( astr )
{
	var c,n=0;
	for(var i=0;i<astr.length;i++)
	{
		c=parseInt(astr.charAt(i));
		if( IsNumeric(c) ) n |= (1 << (c-1));
	}
	return n;
}
function assign_clicks()
{
	var t,x,y;
	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			t=document.getElementById("a"+y+x);
			t.onclick=color_same;
			if (t.captureEvents) t.captureEvents(Event.CLICK);
		}
}
function readCookie(name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}


sud_list = [                  "PPR","LBR",            "XWG","SCN","YWG","SFH","XCY","XYC","3DM","JFH","URT","HUR","XYZ","APE","BUG","GXC","ERT","FXW","FSF","AIC","COQ","PFC","CFC","UFC","ALS","DBL","POM","QFC","NIS","BBB"];
jig_list = [                  "PPR","LBR","LOL",      "XWG","SCN","YWG","SFH","XCY","XYC","3DM","JFH",            "XYZ","APE",      "GXC",                  "AIC",      "PFC","CFC","UFC","ALS","DBL","POM","QFC","NIS","BBB"];
sdx_list = [                  "PPR","LBR",            "XWG","SCN","YWG","SFH","XCY","XYC","3DM","JFH","URT","HUR","XYZ","APE","BUG","GXC",      "FXW","FSF","AIC","COQ","PFC","CFC","UFC","ALS","DBL","POM","QFC","NIS","BBB"];
kil_list = ["KL1","KIO","KCS","PPR","LBR",      "KL4","XWG","SCN","YWG","SFH","XCY","XYC","3DM","JFH", 	 		  "XYZ","APE",      "GXC",      "FXW","FSF","AIC","COQ",      "CFC","UFC","ALS","DBL",      "QFC"];

var jig=0;

function paint_yes_no( thelist, endstage )
{
	var i;
	for(i=0;i<thelist.length;i++)
	{
		if( thelist[i] == endstage ) break;
		document.getElementById("R" + thelist[i]).innerHTML='<font color=#ff0000><b>No</b></font>';
	}
	if(endstage!="NO")
	{
		var d = document.getElementById("R" + endstage);
		if( d )
			d.innerHTML='<font color=#00ff00><b>Yes</b></font>';
		else
			alert('paint_yes_no: no row called ' + "R" + endstage);
	}
}
function reset_yes_no( thelist, amt )
{
	var i;
	for(i=1;i<=amt;i++)
		document.getElementById("R" + i).innerHTML='&nbsp;';
	for(i=0;i<thelist.length;i++)
	{
		var d=document.getElementById("R" + thelist[i])
		if(d) d.innerHTML='&nbsp;';
		else alert('reset_yes_no: no row called ' + "R" + thelist[i]);
	}
}
function backup_yes_no( thelist, stage, amt )
{
	var i,s;
	for(i=stage;i<=6;i++)
		document.getElementById("R" + i).innerHTML='&nbsp;';
	s = stage - amt;
	if( s < 0 ) s = 0;
	for(i=s;i<thelist.length;i++)
	{
		var d=document.getElementById("R" + thelist[i]);
		if( d ) d.innerHTML='&nbsp;';
		else alert('backup_yes_no: no row called ' + "R" + thelist[i]);
	}
}
function padzero( a ) {
	if( !IsNumeric2(a) ) return '00';
	if( a < 10 ) return '0'+a;
	return a;
}
function get_stage( thelist, stratname )
{
	for(var i=0;i<thelist.length;i++)
		if( thelist[i] == stratname ) return 7+i;
	return 0;
}


/*------------------------------------------------------------------------*/
/* Function to colour the board according to what the user has clicked on */
/*------------------------------------------------------------------------*/
var newInput;
function Sudoku1( afield,y,x )
{
	var i,j,cell,t;
	var fval=convert_str2mask(afield.value);

	cell=document.getElementById("a"+y+x);
	cell.removeChild(newInput);
	cell.onclick=color_same;

	if( fval == 0 )
	{
		g[y][x]=0;
		mask[y][x]=511;
		lable_square( y,x,0 );
	}
	else
	{
		if( bit_count(fval) == 1 )
		{
			g[y][x]=bit2int(fval)+1;
			mask[y][x]=0;
			set_square( x,y,g[y][x],2 );
		}
		else
		{
			g[y][x]=0;
			mask[y][x]=fval;
			lable_square( y,x,0 );
		}
	}

	stage=0;
	t=document.getElementById("TestT");
	for(i=0;i<MAX_STRAT;i++)
		t.rows[i*1+offset[i]].cells[1].style.backgroundColor=(stage==i) ? "#777700" : ((((i*1+offset[i])%2)==0)?"#333333":"#222222");
}
function color_same(e)
{
	var targ,x,y,i,t;
	var inputbox,ival='';
	if (!e) var e=window.event;
	if (e.target) targ=e.target;
	else if (e.srcElement) targ=e.srcElement;
	if (targ.nodeType == 3) // defeat Safari bug
		targ=targ.parentNode;

	x=targ.id.charAt(2);
	y=targ.id.charAt(1);
	if( targ.id.charAt(0) == 'w' ) targ = document.getElementById("a" + y + x);
	if( editmode==true )
	{
		targ.onclick=null;

		if( g[y][x] )	// If user clicked on an unknown square..
			ival=g[y][x];
		else
			for(i=0;i<9;i++) if( mask[y][x] & (1 << i) )
				ival=ival + (i*1+1)

		var icell = document.getElementById("cl" + y + x);
		if( icell ) icell.style.display = 'none';
		else targ.innerHTML = "";
		newInput = document.createElement("input");
		newInput.setAttribute("id","iput");
		newInput.setAttribute("maxlength",9);
		newInput.setAttribute("value",ival);
		newInput.className = "iput2";
		newInput.onblur = function() { 	Sudoku1(this,y,x); };
		targ.appendChild(newInput);
		newInput.focus();
	}
	else
	{
		for(j=0;j<9;j++)	// For each square on the board
			for(i=0;i<9;i++)
			{
				// Get the table cell name
				t=document.getElementById("a"+j+i);
				if( g[y][x]==0 )	// If user clicked on an unknown square..
				{
					if( g[j][i]>0 && (mask[y][x] & (1 << (g[j][i]-1))) )
						t.style.backgroundColor='#ddccaa';
					else if( mask[j][i] & mask[y][x] )
						t.style.backgroundColor='#ffeedd';
					else
						t.style.backgroundColor='#ddeeff';
				}
				else // If user clicked on a known number..
				{
					if( (x==i && y==j) || g[j][i]==g[y][x] ) // Highlight other occurances of that number
						t.style.backgroundColor='#ddccaa';
					else if( (mask[j][i] & (1 << (g[y][x]-1))) )  // .. and where its possible
						t.style.backgroundColor='#ffeedd';
					else	// .. otherwise its the normal background color
						t.style.backgroundColor='#ddeeff';
				}
			}
	}
}
//============================================================
// Chaining display
//============================================================
function clear_on_off_color()
{
	var x,y,f;
	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
			for(n=0;n<9;n++)
			{
				f = document.getElementById("w"+y+x+n);
				if(f && f.className ) f.className = '';
			}
}
function convert_x( cellx, n )
{
	var b = 6;
	if( jig==1 && cellx > 3 ) b = 8; // adjustment for jigsaw solver
	return (cellx * 46) + (( n % 3 )*12) + b + (parseInt(cellx / 3)*2);
}

function convert_y( celly, n )
{
	var b = 4;
	if( jig==1 && celly > 3 ) b = 2; // adjustment for jigsaw solver
	if( jig==1 && celly > 6 ) b = 0;
	return (celly * 44) + (parseInt( n / 3 )*13) + b + (parseInt(celly / 3)*2);
}

function on_off_color( cellx, celly, n, strong )
{
	var highlight =  (!strong) ?'fshOFF':'fshON';
	var f = document.getElementById("w"+celly+cellx+n);
	if(f) f.className = highlight;
}

function grn_blue_color( s, highlight, m )
{
	var i,x,y,n,f;
	for(i=0;i<s.length;i+=3)
	{
		y = s.charAt(i)-m;
		x = s.charAt(i+1)-m;
		n = s.charAt(i+2)-m;
		f = document.getElementById("w"+y+x+n);
		if(f) f.className = highlight;
	}
}
function ring_candidate( cellx, celly, n, colour, strong )
{
	var x,y;

	x = convert_x( cellx, n );
	y = convert_y( celly, n );

	jg.setColor(colour);
	jg.setStroke(1);
	jg.drawEllipse(x, y, 11, 12);
	on_off_color( cellx, celly, n, strong );
}

function ring_als( cellx1, celly1, cellx2, celly2, n, colour, strong )
{
	var x1,y1,x2,y2,x3,y3,w,h;

	x1 = convert_x( cellx1, n )+1;
	y1 = convert_y( celly1, n )+1;
	x3 = convert_x( cellx2, n )+1;
	y3 = convert_y( celly2, n )+1;

	x2 = (x1<x3)?x1:x3;
	y2 = (y1<y3)?y1:y3;
	w = Math.abs(x3-x1)+10;
	h = Math.abs(y3-y1)+10;

	jg.setColor(colour);
	jg.setStroke(2);
	jg.drawRect(x2, y2, w, h);

	on_off_color( cellx1, celly1, n, strong );
	on_off_color( cellx2, celly2, n, strong );
}

function connect_candidates( cellx1, celly1, n1, cellx2, celly2, n2, strong, colour, colourweak )
{
	var x1,y1,x2,y2,x3,y3;

	x1 = convert_x( cellx1, n1 )+1;
	y1 = convert_y( celly1, n1 )+1;
	x3 = convert_x( cellx2, n2 )+1;
	y3 = convert_y( celly2, n2 )+1;

	if( y1 < y3 ) y1+=8;
	if( y3 < y1 ) y3+=8;

	if( x1 < x3 ) x1+=8;
	if( x3 < x1 ) x3+=8;

	x2 = Math.abs(x3-x1)/2 + Math.min(x1,x3)-10;
	y2 = Math.abs(y3-y1)/2 + Math.min(y1,y3)-10;
//	if( n1>6 && n2>6 )
//		y2 = Math.abs(y3-y1)/2 + Math.min(y1,y3)+10;

	var Xpoints = new Array(x1,x2,x3);
	var YPoints = new Array(y1,y2,y3);

	if( strong )
	{
		jg.setColor(colour);
		jg.setStroke(3);
		jg.drawPolyline( Xpoints, YPoints );
	}
	else
	{
		jg.setColor(colour);
		jg.setStroke(1);
		jg.drawPolyline( Xpoints, YPoints );
	//	if( x1 < x3 && y1 < y3 ) {
			var Xpoints = new Array(x1-2,x2-2,x3-2);
	//	} else {
	//		var Xpoints = new Array(x1-5,x2-5,x3-5);
	//	}
		var YPoints = new Array(y1+2,y2+2,y3+2);
		jg.drawPolyline( Xpoints, YPoints );
	}
}

function parsemychain( chain, maincolor )
{
	var c,c2,i,n,inside,strong,stack=0;
	var xo,yo,no,x=[0,0,0,0],y=[0,0,0,0],many=0;

	inside = false;

	for(i=0;i<chain.length;i++)
	{
		c = chain.charAt(i,1);
		c2 = chain.charAt(i+1,1);
		if( c =='[' || c =='{' ) inside = true;
		else if( c ==']' || c =='}' )
		{
			inside = false;

		//	alert(x + ' ' + y + ' ' + n);
			if( !many ) {
				ring_candidate(x[0],y[0],n-1,maincolor,strong);
				if( stack > 1 ) {
					connect_candidates( xo, yo, no, x[many], y[many], n-1, strong, maincolor,"#ff8800");
				}
			}
			else // cope with ALS
			{
				ring_als( x[0],y[0], x[1],y[1], n-1, maincolor,strong);
				if( many > 1 )
					ring_als( x[1],y[1], x[2],y[2], n-1, maincolor,strong);
			//	for(j=0;j<=many;j++)
			//		ring_candidate(x[j],y[j],n-1,"#ff0000");

				if( stack > 1 ) {
					x[0] = (x[0]+x[1])/2;
					y[0] = (y[0]+y[1])/2;
					connect_candidates( xo, yo, no, x[0], y[0], n-1, strong, maincolor,"#ff8800");
				}
			}
			many=0;
		}
		else if( c =='+' ) strong = true;
		else if( c =='-' ) strong = false;
		else if( c =='|' ) many++;
		else if( c !=' ' )
		{
			if( inside ) {

				if( c=='A' && c2 == 'L' )
				{
					i+=3;
				}
				else
				{
					if( !many ) {
						xo = x[0];
						yo = y[0];
					}
					y[many] = c.charCodeAt(0)-65;
					if( y[many]==9 ) y[many] = 8;
					x[many] = parseInt(c2)-1;
					i++;
					stack++;
				}
			}
			else
			{
				no = n-1;
				n = parseInt(c);
			}
		}
	}
}
