var rowused = new Array(729);
var colused = new Array(324);

var row2col = new Array(729);
var col2row = new Array(324);

var usermask = new Array(729);
var automask = new Array(729);

var cell2box = "000111222000111222000111222333444555333444555333444555666777888666777888666777888";

var undoList = new Array(81);

var timerID = 0;
var tstart = null;
var killTimer = false;
var mpt = 31;
var minusCell = -1;
var pencilMarks = false;
var palColors = new Array(5);
var curMoves = 0;
var moveArr = new Array();

var req;
function recordScore() {
	if (window.XMLHttpRequest) {
		req = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		req = new ActiveXObject("Microsoft.XMLHTTP");
	}
	if (req) {
		var poststr = moveArr[0];
		for (var i = 1; i < curMoves; i++)
			poststr += '-' + moveArr[i];
		req.onreadystatechange = processReqChange;
		req.open("POST", "/sudoku/submit.php", true);
		req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		req.send('&h='+poststr + '&t='+token);
	}
}

function processReqChange() {
}

function initBeforeGrid() {
	var r = 0, c;
	var colrows = new Array(324);

	for (var i = 0; i < 324; i++) {
		col2row[i] = new Array(9);
		colrows[i] = 0;
		colused[i] = 0;
	}

	for (var i = 0; i < 729; i++) {
		row2col[i] = new Array(4);
		rowused[i] = 0;
		usermask[i] = 0;
		automask[i] = 0;
	}
	
	for (var y = 0; y < 9; y++) for (var x = 0; x < 9; x++)
		for (var i = 0; i < 9; i++) {
			c = y*9+x; row2col[r][0] = c;
			col2row[c][colrows[c]++] = r;
			c = y*9+i+81; row2col[r][1] = c;
			col2row[c][colrows[c]++] = r;
			c = x*9+i+162; row2col[r][2] = c;
			col2row[c][colrows[c]++] = r;
			c = parseInt(cell2box.charAt(y*9+x))*9+i+243;
			row2col[r][3] = c;
			col2row[c][colrows[c]++] = r;
			r++;
		}

	palColors[0] = '#FFFFFF';
	palColors[1] = '#FFBBBB';
	palColors[2] = '#BBFFBB';
	palColors[3] = '#BBBBFF';
	palColors[4] = '#FFFFBB';
}

function updateTimer() {
	if (timerID) clearTimeout(timerID);
	if (!tstart) tstart = new Date();
	if (killTimer) return true;

	var tdate = new Date();
	var tdiff = tdate.getTime() - tstart.getTime();

	var min = Math.floor(tdiff/60000), sec = Math.floor(tdiff/1000-60*min);
	var frmt = min + (sec > 9 ? ":" : ":0") + sec;
	document.getElementById('timer').innerHTML = "Time " + frmt;

	timerID = setTimeout("updateTimer()", 1000);
}

function initAfterGrid() {
	tstart = new Date();
	timerID = setTimeout("updateTimer()", 1000);
}

function getPencilMarks(cellidx) {
	var newstr = "<pre id=\"p" + cellidx +
		"\" style=\"margin: 0px; padding: 0px; font-size: 8pt;\">";
	for (var j = 0; j < 9; j++) {
		var w = cellidx*9+j;
		newstr += (pencilMarks ? rowused[w]+automask[w] == 0 : usermask[w] == 1) ? j+1 : "&nbsp;";
		if (j%3 == 2) {
			if (j < 8) newstr += '\n'; else newstr += '\n';
		} else
			newstr += ' ';
	}
	newstr += "</pre>";
	return newstr;
}

function useRow(r) {
	for (var i = 0; i < 4; i++) {
		var c = row2col[r][i];
		colused[c]++;
		for (var j = 0; j < 9; j++) {
			var r2 = col2row[c][j];
			rowused[r2]++;
			if (rowused[r2] == 1 && pencilMarks) {
				var idx = Math.floor(r2/9);
				celldivs[idx].innerHTML = getPencilMarks(idx);
			}
		}
	}
	return rowused[r] == 4;
}

function unUseRow(r) {
	for (var i = 0; i < 4; i++) {
		var c = row2col[r][i];
		colused[c]--;
		for (var j = 0; j < 9; j++) {
			var r2 = col2row[c][j];
			rowused[r2]--;
			if (rowused[r2] == 0 && pencilMarks) {
				var idx = Math.floor(r2/9);
				celldivs[idx].innerHTML = getPencilMarks(idx);
			}
		}
	}
}

function togglePencilMarks(toon) {
	var i;
	pencilMarks = toon;
	for (i = 0; i < 81; i++) if (curpuz.charAt(i) == ' ') {
		celldivs[i].innerHTML = getPencilMarks(i);
	}
}

function checkPuzzle() {
	for (var i = 0; i < 729; i++) {
		if (rowused[i] != 4) return false;
//		if (curpuz.charAt(i) != solpuz.charAt(i)) return false;
	}
	return true;
}

function mouseClick(e) {
	var idx = getEventId(e);
	if (curCell != idx) return true;
	if (mpt == 0) {
		if (puzzle.charAt(idx) == ' ') {
			ch = ' ';
			newDigit(ch, idx);
		}
	} else if (mpt < 10) {
		if (puzzle.charAt(idx) == ' ') {
			ch = ''+mpt;
			newDigit(ch, idx);
		}
	} else if (mpt < 20) {
		if (curpuz.charAt(idx) == ' ') {
			var ridx = idx*9+mpt-11;
			if (pencilMarks)
				automask[ridx] = 1 - automask[ridx];
			else
				usermask[ridx] = 1 - usermask[ridx];
			celldivs[idx].innerHTML = getPencilMarks(idx);
		}
	} else {
		backColors[idx] = palColors[mpt-31];
	}
	return false;
}

function setMPT(idx) {
	var curmpt = document.getElementById('curmpt');
	if (idx == 0) {
		curmpt.innerHTML = 'X';
		curmpt.style.fontSize = 'medium';
		curmpt.style.backgroundColor = '#ECF8FF';
	} else if (idx < 10) {
		curmpt.innerHTML = idx;
		curmpt.style.fontSize = 'medium';
		curmpt.style.backgroundColor = '#ECF8FF';
	} else if (idx < 20) {
		curmpt.style.fontSize = '60%';
		curmpt.style.backgroundColor = '#ECF8FF';
		curmpt.innerHTML = '&plusmn;' + (idx-10);
	} else {
		curmpt.innerHTML = '&nbsp;'
		curmpt.style.fontSize = 'medium';
		curmpt.style.backgroundColor = palColors[idx-31];
	}
	mpt = idx;
}

function newDigit(ch, idx) {
	var prvch = curpuz.charAt(idx);
	curpuz = curpuz.substr(0, idx) + ch + curpuz.substr(idx+1);

	if (prvch != ' ') {
		celldivs[idx].innerHTML = "&nbsp;";
		unUseRow(idx*9+parseInt(prvch)-1);
	}

	var ok = true;
	if (ch != ' ') {
		moveArr[curMoves++] = idx + '_' + ch;
		ok = useRow(idx*9+parseInt(ch)-1);
		celldivs[idx].innerHTML = ch;
	}
	
	// is the puzzle complete?
	if (curpuz.indexOf(' ') == -1) {
		if (checkPuzzle()) {
			killTimer = true;
			puzzleDone();
			alert("Congratulations!");
		} else {
			alert("There is an error in the puzzle!");
		}
	}

	celltds[idx].style.color = "#999999";
	if (ch != ' ') {
		if (warnon == 2) {
			if (solpuz.charAt(idx) != ch)
				celltds[idx].style.color = "#FF0000";
		} else if (warnon == 1) {
			if (!ok)
				celltds[idx].style.color = "#FF0000";
		}
	}
}

function keyPressed(e) {
	var idx = curCell;
	if (idx >= 0 && puzzle.charAt(idx) == ' ') {
		var code;
		if (!e) var e = window.event;
		if (e.keyCode) code = e.keyCode;
		else if (e.which) code = e.which;
		if (code == 16) return false;
		var ch = String.fromCharCode(code);
		if (ch == '-' || ch == '+') {
			minusCell = idx;
		} else {
			if (ch < '1' || ch > '9') ch = ' ';
			if ((minusCell == idx || e.ctrlKey) && ch != ' ' && curpuz.charAt(idx) == ' ') {
				var ridx = idx*9+parseInt(ch)-1;
				if (pencilMarks)
					automask[ridx] = 1 - automask[ridx];
				else
					usermask[ridx] = 1 - usermask[ridx];
				celldivs[idx].innerHTML = getPencilMarks(idx);
			} else {
				newDigit(ch, idx);
				if (ch == ' ') celldivs[idx].innerHTML = getPencilMarks(idx);
			}
			minusCell = -1;
		}
		return false;
	}
}
