var g_ie_odyssey_suduko_data = new Array();
var g_ie_odyssey_suduko_dataLevels = new Array("veasy", "easy", "med", "hard", "vhard");

for(l in g_ie_odyssey_suduko_dataLevels) {
	g_ie_odyssey_suduko_data[l] = new Array();
}

g_ie_odyssey_suduko_data[0][1] =new Array(".5..1.93..4..26.1..978..2..71..4....56.2.1.83....6..27..4..365..2.65..7..85.9..4.","256417938843926715197835264712348596569271483438569127974183652321654879685792341","2");
g_ie_odyssey_suduko_data[0][2] =new Array("2.......8.36...17....521.....36172..81.....47..28945.....386....68...71.3.......4","291763458536948172784521396453617289819235647672894531147386925968452713325179864","3");

g_ie_odyssey_suduko_data[0]["max"]=359;
g_ie_odyssey_suduko_data[1]["max"]=5860;
g_ie_odyssey_suduko_data[2]["max"]=15217;
g_ie_odyssey_suduko_data[3]["max"]=8887;
g_ie_odyssey_suduko_data[4]["max"]=1569;

var m_version='0.9.3';
var m_dataBlockSize=50;
var m_state;
var m_sizeW = 3;
var m_sizeH = 3;
var m_size = m_sizeH * m_sizeW;
var m_timerID;
var m_puzzleForm;
var m_startTime;
var m_finishedTime;
var m_gameDiv;
var m_gameStateDiv;
var m_needsPaint = false;
var m_gridHeight = 0;

function TBBut(label, icon, fn, help) {
	this.m_label = label;
	this.m_icon = "images/"+icon+".gif";
	this.m_fn = fn;
	this.m_help = help;
}

var m_tbButs = new Array(
	new TBBut("Reload Game", "arrow_refresh", "gameLoad()", "Resets/clears the game"),
	new TBBut("Next Game", "arrow_right", "gameNextGame()", "Loads the next game"),
	new TBBut("Check Results", "tick", "gameCheck()", "Check current answers"),
	new TBBut("Show solution", "cog_go", "gameLoadSolution()", "Show solution"),
	new TBBut("Pause", "clock_pause", "gameTogglePause()", "Pauses the timer"),
	new TBBut("Help", "help", "gameHelp()", "Show instruction page")
);

function GameState(lev, gameID) {
	this.m_level = lev;
	this.m_levelName = g_ie_odyssey_suduko_dataLevels[lev];
	this.m_gameID = gameID;
	var levs = new Array("A", "B", "C", "D", "E");
	this.m_gameTitle = levs[this.m_level]+this.m_gameID;
	
	this.m_game = g_ie_odyssey_suduko_data[lev][gameID];
	this.m_grid = ""+this.m_game[0];
	this.m_pausedTime = 0;
	this.m_cheated = false;
}




function drawGame() {
	var drawData;
	if(m_state.m_pausedTime == 0) {
		drawData = m_state.m_grid;
	}
	else {
		drawData = "";
	}


	var tmpHtml =
		'<table style="border-collapse:collapse;border-style:solid;border-width:2px;border-color:#000000">';
	for(br=0;br<m_sizeH;br++) {
		tmpHtml+="<tr>";
		for(bc=0;bc<m_sizeW;bc++) {
			tmpHtml+='<td style="border-style:solid;border-width:1px;padding:0px;border-color:#000000">';
			tmpHtml+='<table style="border-collapse:collapse">';
			for(r=0;r<m_sizeH;r++) {
				tmpHtml+="<tr>";
				for(c=0;c<m_sizeW;c++) {
					var idx = br*m_size*m_sizeH+bc*m_sizeW + r*m_size + c;
					var val = drawData.substring(idx,idx+1);

					var cid = "CID"+idx;

					if(val == '.' || val == '') {
						val = ' ';
					}
						
					var readonly = m_state.m_game[0].substring(idx,idx+1) != '.';
					
					if(readonly) {					
						tdst= 'padding:0px;border-style:solid;border-width:1px;border-color:#000000;background-color:#ffffff';
					}
					else {
						tdst= 'padding:0px;border-style:solid;border-width:1px;border-color:#000000;background-color:#eeeeee';
					}

					tmpHtml+='<td '+
						'style="'+tdst+'">'+
						'<input maxlength="1" size="1" type="text"'+
						' value="'+val+'"'+
						' name="'+cid+'"'+
						' id="'+cid+'"'+
						' onchange="cellChange(\''+cid+'\')" onkeypress="cellKeyPress(event,\''+cid+'\')"';
					if(readonly) {
						tmpHtml += ' readonly'+
							' style="border:solid 0 #dddddd;height:1.5em;width:1.5em;text-align:center;background-color:#eeeeee"';
							//;font-weight:bold
					}
					else {
						tmpHtml +=
							' style="border:solid 0 #dddddd;height:1.5em;width:1.5em;text-align:center;color:black"';
							//;font-style:normal
					}
					tmpHtml+='>';

					tmpHtml+="</input></td>";
				}
				tmpHtml+="</tr>";
			}
			tmpHtml+="</table>";
			tmpHtml+="</td>";
		}
		tmpHtml+="</tr>";
	}
	tmpHtml+="</table>";

	m_gameDiv.innerHTML = tmpHtml;
	
	
	m_needsPaint = false;

	return tmpHtml;
}

function gameNextGame() {
	var lev = getSelectedLevel();
	var id = getSelectedID();
	
	var m_randomGames = true;
	if(m_randomGames) {
		id = 1+Math.floor(Math.random() * (g_ie_odyssey_suduko_data[lev]["max"]-1));
	}
	else {
		id = id+1;
		if(id > g_ie_odyssey_suduko_data[lev]["max"]) {
			id = 1;
			m_puzzleForm.elements['gameID'].value = id;
			lev++;
			m_puzzleForm.elements['gameLev'].value = lev;
			m_puzzleForm.elements['gameLev'].options[lev].selected=true;
		}
	}
	
	m_puzzleForm.elements['gameID'].value = id;	
	
	gameLoad();	
}

function gameConfirmLooseChanges() {
	if(!m_state || m_state.m_grid == m_state.m_game[0] || m_state.m_grid == m_state.m_game[1]) {
		return true;
	}

	if(confirm('Your current game will be cleared, are you sure?')) {
		return true;
	}
	return false;
}

function showToolTip(x, y, msg) {
	var d = document.getElementById("tooltipDiv");
	if(d) {
		alert(d.style.top+":"+d.style.left+":"+msg+":"+d.innerHTML);
		
		d.innerHTML = msg;
		d.style.top = y;
	}
}

function hideToolTip() {
	showToolTip(-100, -500, "");
}

function gameInit() {
	gameLoad();
	
	if(window.location.search && window.location.search.length>0) {
		var qs = window.location.search.substring(1);		
		var pairs = qs.split('&');
		var params = new Array();
		
		for(i in pairs) {
			p = pairs[i];
			var idx = p.indexOf('=');
			if (idx > 0) {
				var key = p.substring(0,idx);
				var value = p.substring(idx+1);
				params[key] = value;
			}
		}

		var lev = params["p_level"];
		if(lev && lev>=0 && lev <5) {
			m_puzzleForm.elements['gameLev'].value = lev;
			m_puzzleForm.elements['gameLev'].options[lev].selected=true;
		}		
	}
	
	gameNextGame();
	drawGame();
}

function gameLoad() {
	if(!gameConfirmLooseChanges()) {
		return;
	}
	
	m_startTime=0;
	m_finishedTime=0;
	
	m_puzzleForm = document.forms['puzzleForm'];
	m_gameDiv = document.getElementById("gameDiv");
	m_gameStateDiv = document.getElementById("gameStateDiv");
	
	try {
		waitMsg('Loading');

		var lev = m_puzzleForm.elements['gameLev'].value;
		var id = m_puzzleForm.elements['gameID'].value;
		var levName = g_ie_odyssey_suduko_dataLevels[lev];

		//alert("loading "+lev+":"+id);

		var max = g_ie_odyssey_suduko_data[lev]["max"];
		if(id<1 || id>max) {
			errorMsg(
				'Game ID '+levName+'-'+id+' not found, '+
				max+' games are available at the '+levName+' level.'
			);
			return;
		}

		var d = g_ie_odyssey_suduko_data[lev][id];

		if(!d) {
			var uri = document.location.toString();
			var qu = uri.indexOf('?');
			if(qu > 0) {
				uri = uri.substring(0, qu);
			}
						
			var i = uri.lastIndexOf('/');
			
			waitMsg('Retrieving puzzle from game server');

			var b=Math.floor((id-1)/m_dataBlockSize);
			var d=uri.substring(0, i)+"/g/js-"+lev+"-"+b+".js";
			
			tmp = d;
			//alert(d);

			var x;

			try {
				x = new XMLHttpRequest();
			}
			catch(e) {
				try {
					x = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch(e) {
					x = new ActiveXObject("Microsoft.XMLHTTP");
				}
			}
			
			if(!x) {
				errorMsg("Unable to init XMLHttpRequest");
				return;
			}

			x.open("GET", d, false);
			x.send( null );
			
			if((x.status == 200 || x.status == 0) && x.readyState == 4) {
				//alert(x.responseText);
				eval(x.responseText);
				waitMsg("Loaded game data, drawing game...");
			}
			else {
				errorMsg(
					"XMLHttpRequest failed<br>"+
					"status: "+x.status+"<br>"+
					"readyState: "+x.readyState+"<br>"+
					"statusText: "+x.statusText+"<br>"
				);
				return;
			}
			
			d = g_ie_odyssey_suduko_data[lev][id];
			
			if(!d) {
				errorMsg("Error attempting to load game "+lev+"/"+id+":<br>Game with this ID not found");
				return;
			}			
		}
		
		//alert(d);
		
		m_state = new GameState(lev, id);

		drawGame();
		updateTimer();
	}
	catch(e) {
		errorMsg("Error attempting to load game "+lev+"/"+id+":<br>"+e.toString());
		throw e;
	}
}


function gameCheck() {
	for(idx=0; idx<m_size*m_size; idx++) {
	//for(idx=0; idx<2; idx++) {
		var cid="CID"+idx;
		var e = m_puzzleForm.elements[cid];
		var v = e.value;
		//alert (v+":"+m_state.m_game[1][idx]);
		if(v != ' ' && v != m_state.m_game[1].substring(idx, idx+1)) {			
			m_needsPaint = true;
			e.style.color="red";
		}
	}
}

function waitMsg(msg) {
	setMsg(msg+'...<br><img src="wait.gif">');
}

function setMsg(msg) {
	m_gameDiv.innerHTML = '<small>'+msg+'</small>';
}

function errorMsg(msg) {
	setMsg('Error:<br><font color="#ff0000">'+msg+'</font>');
}


function getCid(cid) {
	return parseInt(cid.substring(3,cid.length));
}

function cellChange(cid) {
	var id = getCid(cid);
	var val = m_puzzleForm.elements[cid].value;
	if(val == "") {
		val = " ";
		m_puzzleForm.elements[cid].value = val;
	}
	
	if(val.length > 1) {
		val=val.substring(0, 1);
		m_puzzleForm.elements[cid].value = val;
	}
	
	if(m_state.m_grid.substring(id, id+1) != val) {
		//alert(id+":"+cid+":"+val+":"+m_state.m_grid.substring(id, id+1));

		m_state.m_grid = m_state.m_grid.substring(0,id)+val+m_state.m_grid.substring(id+1,m_state.m_grid.length);

		if(m_state.m_grid == m_state.m_game[1]) {
			m_finishedTime = (new Date()).getTime();
			updateTimer();
		}

		//alert(m_state);

		gamePaintIfRequired();
	}
}


function cellKeyPress(e, cid) {
	startTimer();
	var keynum;
	var keychar;

	if(window.event) // IE
	{
		keynum = e.keyCode;
	}
	else if(e.which) // Netscape/Firefox/Opera
	{
		keynum = e.which;
	}
	else {
		return true;
	}

	if(keynum<=48 || keynum>57) {
		keychar = ' ';
	}
	else {
		keychar = String.fromCharCode(keynum);
	}


	m_puzzleForm.elements[cid].value=keychar;
	
	cellChange(cid);
	
	return true;
}

function gamePaintIfRequired() {
	if(m_needsPaint) {
		drawGame();
	}
}


function gameLoadSolution() {
	if(!gameConfirmLooseChanges()) {
		return;
	}
	
	m_state.m_cheated = true;
	m_state.m_grid = m_state.m_game[1];	
	drawGame();
	m_finishedTime = 1;
	updateTimer();
}

function gameBlur() {
	//gamePause();
}

function gameTogglePause() {
	if(m_state.m_pausedTime == 0) {
		gamePause();
	}
	else {
		gameUnPause();
	}
}

function gamePause() {
	//alert("pause at: "+m_state.m_pausedTime);
	if(m_state.m_pausedTime == 0) {
		m_state.m_pausedTime = (new Date()).getTime();
		updateTimer();
		drawGame();
	}
}

function gameUnPause() {
	//alert("unpause at: "+m_state.m_pausedTime);
	if(m_state.m_pausedTime != 0) {
		if(m_startTime != 0) {
			m_startTime = (new Date()).getTime() - (m_state.m_pausedTime - m_startTime);
		}

		m_state.m_pausedTime = 0;

		drawGame();
		updateTimer();
	}
	else {
		gamePaintIfRequired();
	}
	
	if(m_startTime == 0) {
		m_startTime = (new Date()).getTime();
	}
	
	
}

function gameFocus() {
	//gameUnPause();
}

function gameHelp() {
	gamePause();
	var tmp = "";
	
	for(i in m_tbButs) {
		var b = m_tbButs[i];
		tmp += '<tr><td><img src="'+b.m_icon+
		'"></td><td>'+b.m_help+'</td></tr>';
	}
	
	setMsg(
		'<table>'+
		'<tr><td> </td><th>Description</th></tr>'+
		tmp +
		'</table><br>'+
		'<i>Version '+m_version+'</i>'
	);
}

function startTimer() {
	gameUnPause();
	if(!m_timerID) {
		updateTimer();
		m_timerID = setTimeout("updateTimer()", 1000);
	}
}

function updateTimer() {
	if(m_state.m_pausedTime == 0) {
		var val;

		if(m_startTime>0) {
			var endTime;
			if(m_finishedTime == 0) {
				endTime = (new Date()).getTime();
			}
			else {
				endTime = m_finishedTime;
			}
			
			var elapsed = Math.round((endTime - m_startTime)/1000);
			var sec = elapsed%60;
			var min = Math.round(elapsed/60);

			val = "Time: "+min+":"+(sec<10?"0":"")+sec;
		}
		else {
			val = "Time: --:--";
		}
		
		if(m_state.m_cheated) {
			val = "Time: n/a";
		}
		
		if(m_finishedTime != 0) {
			val += "*";
		}

		m_gameStateDiv.innerHTML = "Game "+m_state.m_gameTitle+", "+val;

		setTimeout("updateTimer()", 1000);
	}
	else {
		m_gameStateDiv.innerHTML = "Paused (click to resume)";
	}
}

function gameLevChange() {
	var lev = getSelectedLevel();
	if(lev != m_state.m_level) {
		m_puzzleForm.elements['gameID'].value = 1;
		gameLoad();
	}
}

function getSelectedID() {
	return parseInt(m_puzzleForm.elements['gameID'].value);
}

function getSelectedLevel() {
	return m_puzzleForm.elements['gameLev'].value;
}
