/*
 *	CHESS LIVE CLASS
 */
 
function ChessLive(baseURL, layout) {
	this.baseURL = baseURL;
	this.layout = layout;
	this.layout.controller = this;

	var me = this;
	setInterval(function() { me.update() }, '3000');
	
}

ChessLive.prototype.stop = function() {
	this.roundid = null;
}

ChessLive.prototype.update = function() {
	var me = this;

	if(!this.roundid)
		return;
		
	$.ajax({
		url: this.baseURL + '/live/' + this.roundid,
		data: { reftime: this.reftime },
		type: "GET",
		dataType: 'jsonp',
		success: function(data) { me.cbUpdate(data) }
	});
}

ChessLive.prototype.round = function(roundid) {
	var me = this;
	this.roundid = roundid;

	$('#' + this.layout.prefix + ' > tbody > tr').remove();
//	$('#' + this.layout.prefix).remove();
	
	if(!this.roundid)
		return;
		
	$.ajax({
		url: this.baseURL + '/live/' + roundid,
		type: "GET",
		dataType: 'jsonp',
		success: function(data) { me.cbRound(data) }
	});
}
			
ChessLive.prototype.load = function(tournamentid, callback) {
	var me = this;
	
	$.ajax({
		url: this.baseURL + '/round/' + tournamentid,
		type: "GET",
		dataType: 'jsonp',
		success: function(data) { callback(data) }
	});
}

ChessLive.prototype.game = function(boardnr) {
	var me = this;

	if(!this.roundid)
		return;
		
	$.ajax({
		url: this.baseURL + '/live/' + this.roundid + '/' + boardnr,
		type: "GET",
		dataType: 'jsonp',
		success: function(data) { me.cbGame(data) }
	});
}

ChessLive.prototype.cbUpdate = function(data) {
	this.tournamentid = data.tournamentid;
	this.roundnr = data.roundnr;
	this.reftime = data.reftime;
	this.layout.onUpdate(data);
}

ChessLive.prototype.cbRound = function(data) {
	this.tournamentid = data.tournamentid;
	this.roundnr = data.roundnr;
	this.reftime = data.reftime;
	this.layout.onNewResults(data);
}

ChessLive.prototype.cbGame = function(game) {
	this.layout.onGame(game);
}

/*
 *	CHESS GAMESTATE CLASS
 */
 
function ChessGameState(index, game) {
	this.offset = index;
	this.game = game;
	this.update = true;
}

ChessLayout.prototype.onFocusClick = function(gamestate) {
			this.onFocus(gamestate);
//			this.onFocusToggle(gamestate);
}

ChessLayout.prototype.onFocus = function(gamestate) {
	if(this.currentGame != gamestate) {
		if(this.currentGame)
			this.hideGame(this.currentGame);
	}

	this.showGame(gamestate);
	this.currentGame = gamestate;
}

ChessLayout.prototype.hideGame = function(gamestate) {
	var el = $('#' + this.id(gamestate.offset, 'header'));
	el.removeClass(this.cls('header-focus'));
	var el = $('#' + this.id(gamestate.offset, 'game'));
	el.removeClass(this.cls('game-focus'));
	el.hide();
	gamestate.open = false;
}

ChessLayout.prototype.showGame = function(gamestate) {
	gamestate.open = true;
	
	if(gamestate.update)
		this.controller.game(gamestate.game.nr);
		
	var el = $('#' + this.id(gamestate.offset, 'header'));
	el.addClass(this.cls('header-focus'));

	// Only do this when there are some games to show
		
//	if(gamestate.game.plies.length > 0) {
		var el = $('#' + this.id(gamestate.offset, 'game'));
		el.addClass(this.cls('game-focus'));
		el.fadeIn('slow');
//	}
}

/*
**	CHESS LAYOUT CLASS
*/

function ChessLayout(prefix, headers) {
	this.prefix = prefix;
	this.headers = headers;
	this.gamestateMap = new Object();
	this.gamestateIndex = new Array(); 
	
	var me = this;
	
	$('html').bind('keydown', function(event) {
		var keycode = event.keyCode;
	
		switch(keycode) {
			case 38:
					me.onFocusChange(-1);
					return false;
			case 40:
					me.onFocusChange(1);
					return false;
			case 37:
					me.onPlyFocusChange(null, -1);
					return false;
			case 39:
					me.onPlyFocusChange(null, 1);
					return false;
			case 36:
					me.onPlyFocus(null, 1);
					return false;
			case 35:
					me.onPlyFocus(null, null);
					return false;
		}
	});
}

ChessLayout.prototype.onNewResults = function(data) {
	var games = data.games;
	var l = games.length;
	
	var table = $('#' + this.id());
	var tbody = table.find('tbody');
	var me = this;
	
	this.gamestateMap = new Object();
	this.gamestateIndex  = new Array();
	
	for(var i = 0; i < l; i++) {
		var game = games[i];
		
		var gamestate = new ChessGameState(i, game);
		
		this.gamestateMap[game.nr] = gamestate;
		this.gamestateIndex[i] = gamestate;
		
		game.pgn = game.plies > 0 ? "*" : "";
		
		var row = $("<tr>");
		row.attr('class', this.cls('header'));
		row.attr('id', this.id(i, 'header'));
		
		row.bind('click', gamestate, function(event) {
			me.onFocusClick(event.data);
		});
		
		var headers = this.headers;
		var ll = headers.length;
		
		for(var j=0; j<ll; j++) {
			var title = headers[j];
			var attr = 'attr-' + title;
			var cell = $("<td>");
			cell.attr('class', this.cls(attr));
			cell.attr('id', this.id(i, attr));
			cell.text(game[title]);
			row.append(cell);
		}

		tbody.append(row);

		row = $('<tr/>');
		
		var cell = $('<td colspan="' + headers.length + '"/>');
		var game = $('<div/>');
		
		game.attr('class', this.cls('game'));
		game.attr('id', this.id(i, 'game'));
		
		cell.append(game);
		row.append(cell);
		tbody.append(row);
	}
	
	if(game.length == 0)
		table.removeClass(this.cls('focus'));
	else
		table.addClass(this.cls('focus'));
}

ChessLayout.prototype.onUpdate = function(data) {
	var l = data.games.length;
	
	for(var i=0; i<l; i++) {
		var game = data.games[i];
		var gamestate = this.gamestateMap[game.nr];
		if(gamestate) {
			var result = $('#' + this.id(gamestate.offset, "attr-result"));
			
			gamestate.result = game.result;
			
			if(gamestate.open || game.result != "")
					result.text(game.result);
				else
					result.text("***");
					
			if(gamestate.open)
				this.controller.game(gamestate.game.nr);
			else
				gamestate.update = true;
		}
	}
}

ChessLayout.prototype.onGame = function(game) {
	var gamestate = this.gamestateMap[game.nr];
	
	if(gamestate == undefined)
		return;
	
	var me = this;
	var nr = gamestate.offset;

	if(gamestate.game.plies)
		if(gamestate.currentPly >= (gamestate.game.plies.length - 1))
				gamestate.currentPly = game.plies.length-1;

	if(gamestate.currentPly == undefined && game.plies)
		gamestate.currentPly = game.plies.length-1;
		
	gamestate.game = game;
	gamestate.update = false;
	
	var headers = this.headers;
	var ll = headers.length;
	
	for(var j=0; j<ll; j++) {
		var title = headers[j];
		var attr = 'attr-' + title;
		var value = game[title];
		if(value);
			$('#' + this.id(nr, attr)).text(value);
	}
	
	if(game.plies == undefined) {
		$('#' + this.id(nr, 'game')).empty().append($('<center/>').text('No game details'));
	} else {
		var img = $('<img/>');
		img.attr('id', this.id(nr, 'image'));
		img.attr('class', this.cls('image'));
		img.attr('height', game.size);
		img.attr('width', game.size);
		
		img.attr('src', this.controller.baseURL + '/fen/' + gamestate.game.fens[gamestate.currentPly]);
		
		var center = $('<center/>');
		
		center.append(img);
		center.append($('<br/>'));

		var whiteClock;
		var blackClock;
		
		if(gamestate.game.whiteClock) {
			whiteClock = $('<div/>');
			whiteClock.attr('class', this.cls('whiteclock'));
			whiteClock.text(gamestate.game.whiteClock.substring(0,8));
			
			blackClock = $('<div/>');
			blackClock.attr('class', this.cls('blackclock'));
			blackClock.text(gamestate.game.blackClock.substring(0,8));
			
			center.append(whiteClock).append(blackClock);
		}

		var prev = $('<span/>');
		prev.attr('class', this.cls('button'));
		prev.bind('click', gamestate, function() {
			me.onPlyFocusChange(gamestate, -1);
		});
		prev.append('&nbsp;&lt;&nbsp;');
		
		var next = $('<span/>');
		next.attr('class', this.cls('button'));
		next.bind('click', gamestate, function() {
			me.onPlyFocusChange(gamestate, 1);
		});
		next.append('&nbsp;&gt;&nbsp;');
		
		center.append(prev).append(' ').append(next);
		
//		var br = $('<div/>');
//		br.attr('style', 'clear: both');
//		center.append(br);
			
		var board = $('<div/>');
		board.attr('class', this.cls('board'));
		board.append(center);
		
		var moves = $('<div/>');
		moves.attr('class', this.cls('moves'));
		
		var l = game.plies.length;
	
		for(var i=1; i<l; i++) {
			moves.append(' ');
			if(i % 2 == 1) {
				var sp = $('<span/>');
				sp.attr('class', this.cls('movenr'));
				sp.html(((i+1)/2) + '.&nbsp');
				moves.append(sp);
			}
			
			var sp = $('<span/>');
			
			sp.attr('class', this.cls('ply'));
			sp.attr('id', this.id(nr + '-' + (i), 'ply'));
				
			var info = {
				gamestate: gamestate,
				ply: i
			};
			
			sp.bind('click', info, function(event) {
				me.onPlyFocus(event.data.gamestate, event.data.ply);
			});
			
			if(i == gamestate.currentPly)
				sp.attr('class', this.cls('ply-focus'));
			
			sp.text(game.plies[i]);
			
			moves.append(sp);
		}

		var pgn = $('<a/>');
		pgn.attr('href', me.controller.baseURL + '/live/' + me.controller.roundid + '/' + game.nr + '.pgn');
		pgn.html('(pgn&nbsp;laden)');
		moves.append(' ');
		moves.append(pgn);
		var br = $('<div/>');
		br.attr('style', 'clear: both');

		$('#' + this.id(nr, 'game')).empty().append(board).append(moves).append(br);
	}
}

ChessLayout.prototype.id = function(nr, suffix) {
	if(nr == undefined) {
		if(suffix == undefined)
			return this.prefix;
		else
			return this.prefix + '-' + suffix;
	}
		
	if(suffix == undefined)
		return this.prefix + '-' + nr;
		
	return this.prefix + '-' + suffix + '-' + nr;
}

ChessLayout.prototype.cls = function(suffix) {
	return 'livegame-' + suffix;
}

ChessLayout.prototype.onPlyFocus = function(gamestate, ply) {
	if(gamestate == undefined)
		if(this.currentGame == undefined)
			return;
		else
			gamestate = this.currentGame;

	var plycount = gamestate.game.plies.length;
	
	if(plycount == 0)
		return;
		
	if(ply == undefined)
		ply = plycount - 1;
	else {
		if(ply >= plycount - 1)
			ply = plycount - 1;
			
		if(ply < 0)
			ply = 0;
	}

	if(gamestate.currentPly != undefined) {
		if(ply == gamestate.currentPly)
			return;
			
		this.hidePly(gamestate, gamestate.currentPly);
	}

	this.showPly(gamestate, ply);
	gamestate.currentPly = ply;
	this.currentGame = gamestate;
}

ChessLayout.prototype.onPlyFocusChange = function(gamestate, delta) {
	if(gamestate == undefined)
		if(this.currentGame == undefined)
			return;
		else
			gamestate = this.currentGame;
			
	if(gamestate.currentPly == undefined)
		this.onPlyFocus(gamestate, 1);
	else
		this.onPlyFocus(gamestate, gamestate.currentPly + delta);
}

ChessLayout.prototype.hidePly = function(gamestate, ply) {
	var el = $('#' + this.id(gamestate.offset + '-' + ply, 'ply'));
	el.removeClass(this.cls('ply-focus'));
}

ChessLayout.prototype.showPly = function(gamestate, ply) {
	var el = $('#' + this.id(gamestate.offset + '-' + ply, 'ply'));
	el.addClass(this.cls('ply-focus'));
	var img = $('#' + this.id(gamestate.offset, 'image'));
	var fen = gamestate.game.fens[ply];
	if(fen != undefined)
		img.attr('src', this.controller.baseURL + '/fen/' + gamestate.game.fens[ply]);
}

ChessLayout.prototype.onFocusNr = function(index) {

	var gamecount = this.gamestateIndex.length;
	
	if(gamecount == 0)
		return;
		
	if(index >= gamecount)
		index = gamecount - 1;
		
	if(index < 0)
		index = 0;
		
	this.onFocus(this.gamestateIndex[index]);
}

ChessLayout.prototype.onFocusToggle = function(gamestate) {
	if(gamestate.open) {
		this.hideGame(gamestate);
		this.currentGame = undefined;
	} else {
		this.showGame(gamestate);
		this.currentGame = gamestate.offset;
	}
}

ChessLayout.prototype.onFocusChange = function(delta) {
	if(this.currentGame == undefined)
		this.onFocusNr(0);
	else
		this.onFocusNr(this.currentGame.offset + delta);
}

