// helper functions:
function div(a, b)
{
    return (a - a % b) / b;
}

// class Piece constructor:
function Piece(location, src, board)
{
    var img;
    
    this.location = location;
    this.src = src;
    this.board = board;
    this.piece_x = this.GetXCoordinate(this.location);
    this.piece_y = this.GetYCoordinate(this.location);
    
    this.element = document.createElement('div');
    //this.element.id = 's' + location;
    this.element.id = Piece.id_counter++;
	this.element.style.position = 'absolute';
	this.element.style.zIndex = 1;
	this.element.style.filter = 'chroma(color=#D0D0D0)';

    this.element.model_class = this;
    img = document.createElement('img');
    img.src = src;
	img.style.backgroundColor = 'transparent';
	img.style.width = '60px';
	img.style.height = '60px';
    this.element.appendChild(img);
    this.board.element.appendChild(this.element);
    this.identifier = this.element.id;
}

// class Piece static members:
Piece.Sources = new Array(  /*  0 = */ "viewer/wk.png",
                            /*  1 = */ "viewer/wq.png", 
                            /*  2 = */ "viewer/wr.png", 
                            /*  3 = */ "viewer/wb.png", 
                            /*  4 = */ "viewer/wkn.png", 
                            /*  5 = */ "viewer/wp.png",
                            /*  6 = */ "viewer/ws.png", 
                            /*  7 = */ "viewer/bk.png", 
                            /*  8 = */ "viewer/bq.png", 
                            /*  9 = */ "viewer/br.png", 
                            /* 10 = */ "viewer/bb.png", 
                            /* 11 = */ "viewer/bkn.png", 
                            /* 12 = */ "viewer/bp.png", 
                            /* 13 = */ "viewer/bs.png" );
                            
Piece.id_counter = 0;

// Displays the Piece according to current pixel coordinates:
Piece.prototype.Display = function()
{
    this.element.style.left = this.piece_x + 'px';
    this.element.style.top = this.piece_y + 'px';
}

// Returns the left (x) pixel coordinate for the square location loc:
Piece.prototype.GetXCoordinate = function(loc)
{
    var x = (loc % 8) * 60;
   
    return x;
}

// Returns the top (y) pixel coordinate for the square location loc:
Piece.prototype.GetYCoordinate = function(loc)
{
    var y = (7 - div(loc, 8)) * 60;
    
    return y;
}

// Displays the Piece according to current square location. Also 
// updates the pixel coordinates accordingly to the location:
Piece.prototype.DisplayFromLocation = function()
{
    this.piece_x = this.GetXCoordinate(this.location);
    this.piece_y = this.GetYCoordinate(this.location);
    
    this.Display();
}

// Starts the moving of this Piece. The magic value 64 for capture means no capture square:
Piece.prototype.MovePiece = function(dest, capture, dest_piece, visible)
{
    if(!visible)
    {
        var piece;
        if(capture < 64)
        {
            this.board.RemovePiece(capture);
        }
        var old_location = this.location;
        this.location = dest;
        
        if(this.src == Piece.Sources[5] && dest > 55)
        {
            this.element.firstChild.src = Piece.Sources[dest_piece];    
            this.src = Piece.Sources[dest_piece];
        }
        else if(this.src == Piece.Sources[12] && dest < 8)
        {
            this.element.firstChild.src = Piece.Sources[dest_piece];    
            this.src = Piece.Sources[dest_piece];
        }
        else if(this.src == Piece.Sources[0] && old_location == 4 && dest == 6)
        {
            piece = this.board.FindPieceAtLocation(7);
            this.board.state = 1;
            piece.MovePiece(5,64,null,false);
        }
        else if(this.src == Piece.Sources[0] && old_location == 4 && dest == 2)
        {
            piece = this.board.FindPieceAtLocation(0);
            this.board.state = 1;
            piece.MovePiece(3,64,null,false);
        }
        else if(this.src == Piece.Sources[7] && old_location == 60 && dest == 62)
        {
            piece = this.board.FindPieceAtLocation(63);
            this.board.state = 1;
            piece.MovePiece(61,64,null,false);
        }
        else if(this.src == Piece.Sources[7] && old_location == 60 && dest == 58)
        {
            piece = this.board.FindPieceAtLocation(56);
            this.board.state = 1;
            piece.MovePiece(59,64,null,false);
        }
        this.board.state = 0;
        return;
    }
    
    if(this.board.state == 1)
    {
        this.startX = this.GetXCoordinate(this.location);
        this.startY = this.GetYCoordinate(this.location);
        this.endX = this.GetXCoordinate(dest);
        this.endY = this.GetYCoordinate(dest);
        
        this.incX = this.endX - this.startX;
        this.incY = this.endY - this.startY;
        
        if(this.incX == 0)
        {
            this.denominator = Math.abs(this.incY);
        }
        else if(this.incY == 0)
        {
            this.denominator = Math.abs(this.incX);
        }
        else if(this.incY < this.incX)
        {
            this.denominator = Math.abs(this.incY);
        }
        else
        {
            this.denominator = Math.abs(this.incX);
        }
        this.cX = 0;
        this.cY = 0;
        this.element.style.zIndex = 2;
        
        this.destination = dest;
        this.capture = capture;
        this.dest_piece = dest_piece;
        this.board.state = 2;
        MovePieceAnimate(this.identifier);
        this.intervalId = setInterval("MovePieceAnimate('" + this.identifier + "')",10);
    }
}

Piece.prototype.MovePieceBackward = function(src_square, src_piece, capture_square, capture_piece)
{
    var piece;
    var old_location = this.location;
    this.location = src_square;    
    if(capture_square < 64)
    {
        this.board.RestorePiece(Piece.Sources[capture_piece], capture_square);
    }
    this.element.firstChild.src = Piece.Sources[src_piece];
    this.src = Piece.Sources[src_piece];       
    
    if(this.src == Piece.Sources[0] && old_location == 6 && this.location == 4)
    {
        piece = this.board.FindPieceAtLocation(5);
        piece.location = 7;
    }
    else if(this.src == Piece.Sources[0] && old_location == 2 && this.location == 4)
    {
        piece = this.board.FindPieceAtLocation(3);
        piece.location = 0;
    }
    else if(this.src == Piece.Sources[7] && old_location == 62 && this.location == 60)
    {
        piece = this.board.FindPieceAtLocation(61);    
        piece.location = 63;
    }
    else if(this.src == Piece.Sources[7] && old_location == 58 && this.location == 60)
    {
        piece = this.board.FindPieceAtLocation(59);    
        piece.location = 56;
    }
}

function MovePieceAnimate(identifier)
{
    var piece;
    var fig = document.getElementById(identifier);
    var mc = fig.model_class;
    
    if(mc.board.state == 2)
    {
        mc.piece_x += 10 * div(mc.cX+mc.incX,mc.denominator);
        mc.piece_y += 10 * div(mc.cY+mc.incY,mc.denominator);
        mc.Display();
        
        if(mc.piece_x == mc.endX && mc.piece_y == mc.endY)
        {
            var old_location;
            
            clearInterval(mc.intervalId);
            if(mc.capture < 64)
            {
                mc.board.RemovePiece(mc.capture);
            }
            
            old_location = mc.location;
            mc.location = mc.destination;
            fig.style.zIndex = 1;
            
            if(mc.src == Piece.Sources[5] && mc.destination > 55)
            {
                mc.element.firstChild.src = Piece.Sources[mc.dest_piece];  
                mc.src = Piece.Sources[mc.dest_piece];
                mc.board.state = 0;
            }
            else if(mc.src == Piece.Sources[12] && mc.destination < 8)
            {
                mc.element.firstChild.src = Piece.Sources[mc.dest_piece];
                mc.src = Piece.Sources[mc.dest_piece];
                mc.board.state = 0;
            }
            else if(mc.src == Piece.Sources[0] && old_location == 4 && mc.destination == 6)
            {
                piece = mc.board.FindPieceAtLocation(7);
                mc.board.state = 1;
                piece.MovePiece(5,64,null,true);
            }
            else if(mc.src == Piece.Sources[0] && old_location == 4 && mc.destination == 2)
            {
                piece = mc.board.FindPieceAtLocation(0);
                mc.board.state = 1;
                piece.MovePiece(3,64,null,true);
            }
            else if(mc.src == Piece.Sources[7] && old_location == 60 && mc.destination == 62)
            {
                piece = mc.board.FindPieceAtLocation(63);
                mc.board.state = 1;
                piece.MovePiece(61,64,null,true);
            }
            else if(mc.src == Piece.Sources[7] && old_location == 60 && mc.destination == 58)
            {
                piece = mc.board.FindPieceAtLocation(56);
                mc.board.state = 1;
                piece.MovePiece(59,64,null,true);
            }
            else
            {
                mc.board.state = 0;
            }
        }
        else
        {
            mc.cX = (mc.cX+mc.incX) % mc.denominator;
            mc.cY = (mc.cY+mc.incY) % mc.denominator;
        }
    }
    fig = null;
}

// class Board constructor:
function Board(display_id)
{
	var img;

	img = document.createElement('img');
	img.src = "viewer/board.png";
	img.style.position = 'absolute';
	img.style.left = '0px';
	img.style.top = '0px';
	img.style.width = '480px';
	img.style.height = '480px';
	this.element = document.getElementById(display_id);
	this.element.style.position = 'absolute';
	this.element.zIndex = 0;
	this.element.filter = 'chroma(color=#D0D0D0)';
	this.element.appendChild(img);
    this.state = 0;
    this.pieces = new Array();
    this.InitPieces();
}

// class Board methods:
Board.prototype.InitPieces = function()
{
    this.ClearBoard();
    this.pieces.push(new Piece(0,Piece.Sources[2],this));
    this.pieces.push(new Piece(1,Piece.Sources[4],this));
    this.pieces.push(new Piece(2,Piece.Sources[3],this));
    this.pieces.push(new Piece(3,Piece.Sources[1],this));
    this.pieces.push(new Piece(4,Piece.Sources[0],this));
    this.pieces.push(new Piece(5,Piece.Sources[3],this));
    this.pieces.push(new Piece(6,Piece.Sources[4],this));
    this.pieces.push(new Piece(7,Piece.Sources[2],this));
    this.pieces.push(new Piece(8,Piece.Sources[5],this));
    this.pieces.push(new Piece(9,Piece.Sources[5],this));
    this.pieces.push(new Piece(10,Piece.Sources[5],this));
    this.pieces.push(new Piece(11,Piece.Sources[5],this));
    this.pieces.push(new Piece(12,Piece.Sources[5],this));
    this.pieces.push(new Piece(13,Piece.Sources[5],this));
    this.pieces.push(new Piece(14,Piece.Sources[5],this));
    this.pieces.push(new Piece(15,Piece.Sources[5],this));
    
    this.pieces.push(new Piece(48,Piece.Sources[12],this));
    this.pieces.push(new Piece(49,Piece.Sources[12],this));
    this.pieces.push(new Piece(50,Piece.Sources[12],this));
    this.pieces.push(new Piece(51,Piece.Sources[12],this));
    this.pieces.push(new Piece(52,Piece.Sources[12],this));
    this.pieces.push(new Piece(53,Piece.Sources[12],this));
    this.pieces.push(new Piece(54,Piece.Sources[12],this));
    this.pieces.push(new Piece(55,Piece.Sources[12],this));
    this.pieces.push(new Piece(56,Piece.Sources[9],this));
    this.pieces.push(new Piece(57,Piece.Sources[11],this));
    this.pieces.push(new Piece(58,Piece.Sources[10],this));
    this.pieces.push(new Piece(59,Piece.Sources[8],this));
    this.pieces.push(new Piece(60,Piece.Sources[7],this));
    this.pieces.push(new Piece(61,Piece.Sources[10],this));
    this.pieces.push(new Piece(62,Piece.Sources[11],this));
    this.pieces.push(new Piece(63,Piece.Sources[9],this));
}

Board.prototype.Display = function()
{
    for(var i = 0; i < this.pieces.length; i++)
    {
        this.pieces[i].DisplayFromLocation();
    }
}

Board.prototype.RemovePiece = function(location)
{
    var piece = this.FindPieceAtLocation(location);
    this.element.removeChild(piece.element);
    this.pieces.splice(this.FindPieceIndexAtLocation(location), 1);
}

Board.prototype.ClearBoard = function()
{
    for(var i = 0; i < this.pieces.length; i++)
    {
        this.element.removeChild(this.pieces[i].element);
    }
    this.pieces.splice(0, this.pieces.length);
}

Board.prototype.RestorePiece = function(src, location)
{
    var piece = new Piece(location, src, this);
    this.pieces.push(piece);
}

Board.prototype.FindPieceAtLocation = function(location)
{
    for(var i = 0; i < this.pieces.length; i++)
    {
        if(this.pieces[i].location == location)
        {
            return this.pieces[i];
        }
    }
}

Board.prototype.FindPieceIndexAtLocation = function(location)
{
    for(var i = 0; i < this.pieces.length; i++)
    {
        if(this.pieces[i].location == location)
        {
            return i;
        }
    }
}

Board.prototype.MakeMove = function(move, visible)
{   
    var src_square, src_piece, dest_square, dest_piece, piece;
    
    if(this.state == 0)
    {
        this.state = 1;
        src_square = parseInt(move.substring(0,2),10);
        src_piece = parseInt(move.substring(2,4),10);
        dest_square = parseInt(move.substring(4,6),10);
        dest_piece = parseInt(move.substring(6,8),10);
        var piece = this.FindPieceAtLocation(src_square);
        piece.MovePiece(dest_square,parseInt(move.substring(8,10),10),dest_piece,visible);  
    }
}

Board.prototype.MakeMoveBackward = function(move)
{
    var src_square, src_piece, dest_square, dest_piece, piece;
    if(this.state == 0)
    {
        this.state = 1;
        src_square = parseInt(move.substring(0,2),10);
        src_piece = parseInt(move.substring(2,4),10);
        dest_square = parseInt(move.substring(4,6),10);
        dest_piece = parseInt(move.substring(6,8),10);
        var piece = this.FindPieceAtLocation(dest_square);
        piece.MovePieceBackward(src_square,src_piece,parseInt(move.substring(8,10),10),parseInt(move.substring(10,12),10));
        this.state = 0;
    }
}

// class Game constructor:
function Game(display_id)
{
    this.display_id = display_id;
}

Game.prototype.SetInformation = function(event_name, site, date, round, white, black, result, moves)
{
    this.event_name = event_name;
    this.site = site;
    this.date = date;
    this.round = round;
    this.white = white;
    this.black = black;
    this.result = result;
    this.moves = moves.split('|');
    this.move_index = 0;
    this.board = new Board(this.display_id);
}

Game.prototype.Display = function()
{
    this.board.Display();
}

Game.prototype.MakeMoveForward = function()
{
    if(this.board.state == 0 && this.move_index < this.moves.length)
    {
        this.board.MakeMove(this.moves[this.move_index], true);
        this.move_index++;
    }
}

Game.prototype.MakeMoveBackward = function()
{
    if(this.board.state == 0 && this.move_index > 0)
    {
        this.move_index--;
        this.board.MakeMoveBackward(this.moves[this.move_index]);
        this.board.Display();
    }
}

Game.prototype.ShowPositionAfterMoves = function(move_number)
{
    if(this.board.state == 0)
    {
        this.board.InitPieces();
        this.move_index = 0;
        for(var i = 0; i < this.moves.length && i < move_number; i++)
        {
            this.board.MakeMove(this.moves[this.move_index], false); 
            this.move_index++;
        }   
        this.board.Display();
    }
}

