

// Copyright (c) Lee Chapman, 2006
// webmaster@cambridgechess.org.uk

var GameHistory = new Array();
var Comments = new Array();

var position = 0;
var target = 0;
var wtaken = 1;
var btaken = 1;
var visible = 1;
var page = 15;
var tick = 10;

var animationOffsetX = 0;
var animationOffsetY = 0;

if (navigator)
	if (navigator.appName)
		if (navigator.appName.indexOf("Microsoft") >= 0)
			animationOffsetX = -16;

function PageUp()
{
	visible -= page;

	if (visible < 1)
		visible = 1;

	HideRows();
}

function PageDown()
{
	visible += page;

	if (visible > Math.ceil((GameHistory.length) / 2) - page)
		visible = Math.ceil((GameHistory.length) / 2) - page;

	HideRows();
}

function LineUp()
{
	if (visible > 1)
		visible--;

	HideRows();
}

function LineDown()
{
	if (visible < GameHistory.length / 2 - page)
		visible++;

	HideRows();
}

function HideRows()
{
	var i = 1;

	while (true)
	{
		var row = GetElement("row" + i);

		if (!row)
			break;

		var style = i < visible || i > visible + page - 1 ? "hidden" : "";

		if (row.className != style)
			row.className = style;

		i++;
	}
}

function EnsureVisible(position)
{
	if (position < 1)
		position = 1;

	if (position < visible)
	{
		visible = position;
		HideRows();
	}
	else if (position >= visible + page)
	{
		visible = position - page + 1;
		HideRows();
	}
}

function Board()
{
}

Board.prototype.Save = function ()
{
	return "<position><standard /></position>";
}

Board.prototype.Make = function ()
{
	this.Place("a2", new WhitePawn());
	this.Place("b2", new WhitePawn());
	this.Place("c2", new WhitePawn());
	this.Place("d2", new WhitePawn());
	this.Place("e2", new WhitePawn());
	this.Place("f2", new WhitePawn());
	this.Place("g2", new WhitePawn());
	this.Place("h2", new WhitePawn());

	this.Place("a7", new BlackPawn());
	this.Place("b7", new BlackPawn());
	this.Place("c7", new BlackPawn());
	this.Place("d7", new BlackPawn());
	this.Place("e7", new BlackPawn());
	this.Place("f7", new BlackPawn());
	this.Place("g7", new BlackPawn());
	this.Place("h7", new BlackPawn());

	this.Place("a1", new WhiteRook());
	this.Place("b1", new WhiteKnight());
	this.Place("c1", new WhiteBishop());
	this.Place("d1", new WhiteQueen());
	this.Place("e1", new WhiteKing());
	this.Place("f1", new WhiteBishop());
	this.Place("g1", new WhiteKnight());
	this.Place("h1", new WhiteRook());

	this.Place("a8", new BlackRook());
	this.Place("b8", new BlackKnight());
	this.Place("c8", new BlackBishop());
	this.Place("d8", new BlackQueen());
	this.Place("e8", new BlackKing());
	this.Place("f8", new BlackBishop());
	this.Place("g8", new BlackKnight());
	this.Place("h8", new BlackRook());
}

function GetElement(id)
{
	return document.getElementById(id);
}

function SetImage(id, src)
{
	GetElement(id).src = src;
}

function GetImage(id)
{
	var image = GetElement(id);

	if (!image)
		return null;

	return image.src;
}

Board.prototype.Place = function (square, piece)
{
	SetImage(square, piece.Image);
}

function Animation(action, image, from, to, replacement)
{
	this.image = image;
	this.tick = 3;
	this.nextAction = action;
	this.x1 = this.GetX(from);
	this.y1 = this.GetY(from);
	this.x2 = this.GetX(to);
	this.y2 = this.GetY(to);
	this.from = from;
	this.to = to;
	this.replacement = replacement;

	this.count = 0;

	var sx = this.x1 < this.x2 ? this.x2 - this.x1 : this.x1 - this.x2;
	var sy = this.y1 < this.y2 ? this.y2 - this.y1 : this.y1 - this.y2;

	this.steps = (sx < sy ? sy : sx) / this.tick;

	this.deltaX = (this.x2 - this.x1) / this.steps;
	this.deltaY = (this.y2 - this.y1) / this.steps;
}

Animation.prototype.GetX = function(square)
{
	return (square.charCodeAt(0) - "a".charCodeAt(0)) * 34;
}

Animation.prototype.GetY = function(square)
{
	return (8 - parseInt(square.charAt(1))) * 34;
}

Animation.prototype.Run = function ()
{
	SetImage("animation", this.image);

	if (this.steps <= 0)
	{
		action = this.nextAction;
		SetImage(this.to, GetImage("animation"));

		GetElement("animation").style.visibility = "hidden";
	}
	else
	{
		var piece = GetElement("animation").style;

		piece.left = (animationOffsetX + this.x1 + (this.deltaX * this.count)) + "px";
		piece.top = (animationOffsetY + this.y1 + (this.deltaY * this.count)) + "px";

		if (this.count == 0)
		{
			GetElement("animation").style.visibility = "visible";
			SetImage(this.from, this.replacement);
		}

		this.steps--;
		this.count++;
	}

	if (action)
		setTimeout("action.Run()", action.tick);
}

function Move(from, to, notation)
{
	this.From = from;
	this.To = to;
	this.Notation = notation;
	this.captive = false;
	this.castlingKingSide = notation == "0-0";
	this.castlingQueenSide = notation == "0-0-0";
}

Move.prototype.Save = function ()
{
	return "<move><from>" + this.From + "</from><to>" + this.To + "</to><notation>" + this.Notation + "</notation></move>";
}

Move.prototype.Make = function (direction)
{
	if (!this.To || !this.From)
		return;

	var animation;

	if (direction == 1)
	{
		var taken;

		this.enPassant = IsPiece("square", GetImage(this.To)) && IsPiece("pawn", GetImage(this.From)) && File(this.From) != File(this.To);

		if (this.enPassant)
			taken = GetImage(Offset(this.To, 0, Rank(this.From) - Rank(this.To)));
		else
			taken = GetImage(this.To);

		if (taken.indexOf("/white/") >= 0)
		{
			SetImage("wt" + wtaken, taken);
			this.captive = true;
			wtaken++;
		}
		else if (taken.indexOf("/black/") >= 0)
		{
			SetImage("bt" + btaken, taken);
			this.captive = true;
			btaken++;
		}

		if (this.enPassant)
			SetImage(Offset(this.To, 0, Rank(this.From) - Rank(this.To)), "/images/set/square");

		var next = action;

		if (this.castlingKingSide)
			next = new Animation(next, GetImage(Offset(this.From, 3, 0)), Offset(this.From, 3, 0), Offset(this.From, 1, 0), "/images/set/square");
		else if (this.castlingQueenSide)
			next = new Animation(next, GetImage(Offset(this.From, -4, 0)), Offset(this.From, -4, 0), Offset(this.From, -1, 0), "/images/set/square");

		animation = new Animation(next, GetImage(this.From), this.From, this.To, "/images/set/square");
	}
	else
	{
		var piece = GetImage(this.To);
		var anim = piece;

		if (piece.indexOf("/white/") >= 0)
		{
			if (this.captive)
				btaken--;

			piece = GetImage("bt" + btaken);

			if (this.captive)
				SetImage("bt" + btaken, "/images/set/square");
		}
		else
		{
			if (this.captive)
				wtaken--;

			piece = GetImage("wt" + wtaken);

			if (this.captive)
				SetImage("wt" + wtaken, "/images/set/square");
		}

		if (this.enPassant)
		{
			SetImage(Offset(this.To, 0, Rank(this.From) - Rank(this.To)), piece);
			piece = "/images/set/square";
		}

		var next = action;

		if (this.castlingKingSide)
			next = new Animation(next, GetImage(Offset(this.To, -1, 0)), Offset(this.To, -1, 0), Offset(this.To, 1, 0), "/images/set/square");
		else if (this.castlingQueenSide)
			next = new Animation(next, GetImage(Offset(this.To, 1, 0)), Offset(this.To, 1, 0), Offset(this.To, -2, 0), "/images/set/square");

		animation = new Animation(next, anim, this.To, this.From, piece);
	}

	action = animation;
}

function WhitePawn()
{
	this.Image = "/images/set/white/pawn";
}

function BlackPawn()
{
	this.Image = "/images/set/black/pawn";
}

function WhiteRook()
{
	this.Image = "/images/set/white/rook";
}

function BlackRook()
{
	this.Image = "/images/set/black/rook";
}

function WhiteKnight()
{
	this.Image = "/images/set/white/knight";
}

function BlackKnight()
{
	this.Image = "/images/set/black/knight";
}

function WhiteBishop()
{
	this.Image = "/images/set/white/bishop";
}

function BlackBishop()
{
	this.Image = "/images/set/black/bishop";
}

function WhiteQueen()
{
	this.Image = "/images/set/white/queen";
}

function BlackQueen()
{
	this.Image = "/images/set/black/queen";
}

function WhiteKing()
{
	this.Image = "/images/set/white/king";
}

function BlackKing()
{
	this.Image = "/images/set/black/king";
}

var action;

function Next()
{
	if (position < GameHistory.length - 1)
		Position(position + 1);
}

function Previous()
{
	if (position > 0)
		Position(position - 1);
}

function Go(position)
{
	tick = 10;
	Position(position);
}

function Position(index)
{
	if (position == index)
		return;

	target = index;

	if (action == null)
	{
		action = new MakeMove();
		action.Run();
	}
}

function ResetMoveList(position)
{
	var element = GetElement("m" + position);

	if (element)
		element.style.fontWeight = "normal";
}


function SetMoveList(position)
{
	var element = GetElement("m" + position);

	if (element)
		element.style.fontWeight = "bold";

	if (position < Comments.length && Comments[position])
	{
		var thisComment = "cc" + Comments[position];

		element = GetElement(thisComment);

		if (element)
		{
			var comment = GetElement("comment");

			comment.innerHTML = element.innerHTML;
		}
	}
}

function MakeMove()
{
}

MakeMove.prototype.Run = function ()
{
	if (position == target)
	{
		action = null;
		return;
	}

	if (position < target)
	{
		ResetMoveList(position);

		position += 1;

		SetMoveList(position);

		EnsureVisible(Math.floor((position + 1) / 2));

		GameHistory[position].Make(1);
	}
	else
	{
		ResetMoveList(position);
		SetMoveList(position - 1);

		EnsureVisible(Math.floor(position / 2));

		GameHistory[position].Make(-1);

		position -= 1;
	}

	if (action)
		setTimeout("action.Run()", tick);
}

function Click(square)
{

}



function Offset(square, deltaFile, deltaRank)
{
	var offset = null;
	var rank = Rank(square);
	var file = File(square);

	rank += deltaRank;
	file += deltaFile;

	if (rank >= 1 && rank <= 8 && file >= 1 && file <= 8)
		offset = "abcdefgh".charAt(file - 1) + rank;

	return offset;
}

function IsPiece(piece, src)
{
	if (!src)
		return false;

	return src.indexOf("/" + piece) >= 0;
}

function Rank(square)
{
	return parseInt(square.charAt(1));
}

function File(square)
{
	return square.charCodeAt(0) - "a".charCodeAt(0) + 1;
}

function ShowEnd()
{
	tick = 2000;
	Position(GameHistory.length - 1);
}

function ShowStart()
{
	tick = 10;
	Position(0);
}

