///////////////////////////////////////////////////////////////////////////////
// Silverlight extensions

if(window.Sys == null)
	window.Sys= {};
if(window.Sys.Silverlight == null)
	window.Sys.Silverlight= {};

if(Silverlight.createDelegate == null)
{
	Silverlight.createDelegate= function(instance, method) {
		return function() { return method.apply(instance, arguments); } };
}

if(window.$get == null)
	window.$get= function(id) { return document.getElementById(id); };

///////////////////////////////////////////////////////////////////////////////
// HTML code-behind

var chessNavigator, chessScene, highlightedAnchor, isPlaying;

function addAnchor(cell, plyIndex, text)
{
	var el= document.createElement("a");
	el.id= "a" + plyIndex;
	el.href= "javascript:setPly(" + plyIndex + ")";
	el.innerHTML= text;
	cell.appendChild(el);
}

function createChessControl(parentElement)
{
	//var sourceFileName= "Scene.xaml";
	//var controlId= parentElement.id + "_Control";
	//var properties= { width: 710, height: 525, version: "0.9" };
	var scene= new SilverlightChessViewer.Scene();
	//var events= { onLoad: Sys.Silverlight.createDelegate(scene, scene.handleLoad) };
	
	//Sys.Silverlight.createObject(sourceFileName, parentElement, controlId, properties, events, controlId);
	
	
    Silverlight.createObjectEx(
	{
	    source: 'Scene.xaml', 
	    parentElement: parentElement,
	    id: parentElement.id + "_Control", 
	    properties:
	    {
	        width:'710', 
	        height:'525', 
	        version:'1.0',
	        inplaceInstallPrompt: true
	    }, 
	    events:
	    {
	        onError: null, 
	        onLoad: Silverlight.createDelegate(scene, scene.handleLoad), 
	        onResize: null
	    }, 
	    context:null
	});
	
	return scene;
}

function dumpBoard(board)
{
	var s= "";
	for(var i= 0; i < 8; ++i)
	{
		s += "\n";
		for(var j= 0; j < 8; ++j)
		{
			var piece= board[i][j];
			if(piece != null && (piece._position.row != i || piece._position.column != j))
				throw piece;
			s += piece == null ? "." : piece._id.charAt(0) == "B" ? piece._type.glyph.toLowerCase() : piece._type.glyph;
		}
	}
	return s;
}

function getMoveDescription(state)
{
	var pgnText= state.pgnText.replace(/\d+\.+\s*/, "");
	if(pgnText == "")
		return "";
	
	// Determine the side.
	var description= state.plyIndex % 2 == 0 ? "Black " : "White ";
	
	// Determine if the current move is a castling move.
	if(pgnText.indexOf("O-O") >= 0)
		return description + (pgnText.indexOf("-O-") >= 0 ? "queen" : "king") + "-side castle";
	
	// Determine the piece name.
	var piece= Chess.Piece.Types[pgnText.charAt(0)];
	if(piece == null)
		piece= Chess.Piece.Pawn;
	description += piece.name.toLowerCase();
	
	// Determine any capture.
	if(state.capturedPiece != null)
	{
		description += " takes " + state.capturedPiece.getName().toLowerCase();
		description += state.isEnPassant ? " " + "en passant".link("http://en.wikipedia.org/wiki/En_passant")
			+ " while moving to " : " at ";
	}
	else
		description += " moves to ";
	
	// Determine the destination.
	var m= /[a-h][1-8]/.exec(pgnText);
	description += m[0].toUpperCase();
	
	// Determine any promotion.
	var i= pgnText.indexOf("=");
	if(i >= 0)
		description += " and is promoted to a " + Chess.Piece.Types[pgnText.charAt(i + 1)].name;
	
	// Determine the check mode.
	description += [ "", " (check)", " (checkmate)" ][state.checkMode];
	
	return description;
}

function onMoveCompleted()
{
	if(isPlaying)
	{
		if(chessNavigator.isAtFinish())
			stopPlaying();
		else
			window.setTimeout("nextButton_onclick()", 1); // prevent FF "busy script" dialog
	}
}

function setPly(plyIndex)
{
	if(!isPlaying)
	{
		var changes= chessNavigator.setCurrentPly(plyIndex);
		updateBoard(changes);
	}
}

function stopPlaying()
{
	var playButton= $get("playButton");
	playButton.value= "Play";
	isPlaying= false;
	updateButtons();
	if(chessNavigator.isAtFinish())
		$get("beginButton").focus();
	else
		$get("playButton").focus();
}

function updateBoard(changes)
{
	if(changes == null)
		return;
	if(highlightedAnchor != null)
		highlightedAnchor.className= "";
	var currentMoveElement= $get("currentMoveElement");
	currentMoveElement.innerHTML= getMoveDescription(changes);
	var haveSetHandler= !isPlaying;
	for(var i= 0; i < changes.length; ++i)
	{
		var change= changes[i];
		if(haveSetHandler || (i < changes.length - 1 && !change.to.isOffBoard()))
			chessScene.movePiece(change.id, change.to, change.glyph);
		else
		{
			chessScene.movePiece(change.id, change.to, change.glyph, "onMoveCompleted");
			haveSetHandler= true;
		}
	}
	highlightedAnchor= $get("a" + changes.plyIndex);
	highlightedAnchor.className= "currentMove";
	updateButtons();
}

function updateButtons()
{
	var beginButton= $get("beginButton");
	var backButton= $get("backButton");
	beginButton.disabled= backButton.disabled= isPlaying || chessNavigator.isAtStart();
	var playButton= $get("playButton");
	var nextButton= $get("nextButton");
	var endButton= $get("endButton");
	nextButton.disabled= endButton.disabled= isPlaying || chessNavigator.isAtFinish();
	playButton.disabled= !isPlaying && chessNavigator.isAtFinish();
}

///////////////////////////////////////////////////////////////////////////////
// handlers for HTML events

function body_onload()
{
	chessScene= createChessControl($get("chessControlHostElement"));
	gameSelect_onchange();
}

function gameSelect_onchange()
{
	$get("pgnTextArea").value= chessGames[$get("gameSelect").selectedIndex];
}

function body_onkeydown(ev)
{
	if(chessNavigator == null || isPlaying || ev.altKey)
		return;
	switch(ev.keyCode)
	{
	case 35: // end
		endButton_onclick();
		break;
	case 36: // home
		beginButton_onclick();
		break;
	case 37: // left
		backButton_onclick();
		break;
	case 39: // right
		nextButton_onclick();
		break;
	default:
		return;
	}
	if(ev.preventDefault != null)
		ev.preventDefault(); // Firefox
	else
		ev.returnValue= false; // Internet Explorer
}

function changeGame_onclick()
{
	if(isPlaying)
		stopPlaying();
	$get("selectedGameElement").style.display= "none";
	$get("selectingGameElement").style.display= "";
	$get("beginButton").disabled= $get("backButton").disabled= $get("playButton").disabled= $get("nextButton").disabled= $get("endButton").disabled= true;
}

function loadButton_onclick()
{
	if(!chessScene.hasLoaded())
		return;
	$get("moveListElement").innerHTML= "";
	var parser= new Chess.Parser($get("pgnTextArea").value);
	var newChessNavigator= parser.parse();
	if(newChessNavigator != null)
	{
		if(isPlaying)
			stopPlaying();
		chessNavigator= newChessNavigator;
		var plyLabels= chessNavigator.getPlyLabels();
		var moveListTable= $get("moveListTable");
		while(moveListTable.rows.length > 1)
			moveListTable.deleteRow(1);
		var row= moveListTable.insertRow(-1);
		var cell= row.insertCell(-1);
		cell.colSpan= 6;
		cell.className= "start";
		addAnchor(cell, 0, "start");
		for(var i= 1; i < plyLabels.length; ++i)
		{
			if(i % 2 != 0)
			{
				row= plyLabels.length >= i * 2
					? moveListTable.insertRow(-1)
					: moveListTable.rows[(i + 1 - 2 * Math.floor((plyLabels.length - 2) / 4)) / 2];
				cell= row.insertCell(-1);
				cell.className= "n";
				cell.innerHTML= (i + 1) / 2 + ".";
				cell= row.insertCell(-1);
				cell.className= "w";
			}
			else
			{
				cell= row.insertCell(-1);
				cell.className= "b";
			}
			addAnchor(cell, i, plyLabels[i]);
		}
		highlightedAnchor= $get("a0");
		highlightedAnchor.className= "currentMove";
		chessScene.placePieces();
		updateButtons();
		el= $get("selectingGameElement");
		el.style.display= "none";
		el= $get("selectedGameElement");
		el.style.display= "";
	}
}

function beginButton_onclick()
{
	var changes= chessNavigator.begin();
	updateBoard(changes);
	if($get("beginButton").disabled)
		$get("playButton").focus();
}

function backButton_onclick()
{
	var changes= chessNavigator.back();
	updateBoard(changes);
	if($get("backButton").disabled)
		$get("playButton").focus();
}

function playButton_onclick()
{
	if(isPlaying)
		stopPlaying();
	else
	{
		var playButton= $get("playButton");
		playButton.value= "Stop";
		isPlaying= true;
		nextButton_onclick();
	}
}

function nextButton_onclick()
{
	var changes= chessNavigator.next();
	updateBoard(changes);
	var playButton= $get("playButton");
	if(playButton.disabled)
		$get("beginButton").focus();
	else if($get("nextButton").disabled)
		playButton.focus();
}

function endButton_onclick()
{
	var changes= chessNavigator.end();
	updateBoard(changes);
	if($get("endButton").disabled)
		$get("beginButton").focus();
}

