/*****************************************
JSGameLib

History:

[v1.1 02/04/2007]
- JSBoardGame.setGameSize()
- change preloadImages (PRELOAD_SPLASH, PRELOAD_SPRITE options)

******************************************/

var imgList = new Array();
var imgcount = 0;
var langdata = new Array();
var preload_image = new Array();
var jsgamecode;

function trad(tok) { return langdata[tok]; }

function getel(s) { return document.getElementById(s); }

function extendClass(subClass, baseClass) {
/*
   function inheritance() {}
   inheritance.prototype = baseClass.prototype;

   subClass.prototype = new inheritance();
   subClass.prototype.constructor = subClass;
   subClass.baseConstructor = baseClass;
   subClass.superClass = baseClass.prototype;
*/
   subClass.prototype = new baseClass();
   subClass.prototype.constructor = subClass;
}

/*
function Manager(first, last, id, department) {
    Manager.baseConstructor.call(this, first, last, id);
    this.department = department;
}

KevLinDev.extend(Manager, Employee); 
*/

/* ============================================== */
/* ==== JLibCommon library ====================== */
/* ============================================== */
function JLibCommon() {

    /* ==== rand() ============================== */
    // returns a random number [min,max]
    this.rand = function(min, max) {
        if (max <= min) return min;
        var ran_number = Math.floor(Math.random()*(max-min+1));
        return ran_number + min;
    }
    
    /* ==== padl() ============================== */
    // left padding
    this.padl = function( str, n, padchar ) {
        var i;
        var s = '' + str;
        var k = str.length;
        for (i = k; i < n; i++) {
            s = padchar + s;
        }
        return s;
    }

    /* ==== padr() ============================== */
    // right padding
    this.padr = function( str, n, padchar ) {
        var i;
        var s = '' + str;
        var k = str.length;
        for (i = k; i < n; i++) {
            s = s + padchar;
        }
        return s;
    }
    
    this.trim = function( str ) {    
        var n, i, s, a, b;
        if (typeof(str) != "string") return str;
        n = str.length;
        i = 0;
        a = 0;
        b = n;
        while (a < n && str.charAt(a) == ' ') a++;
        while (b > 0 && b > a && str.charAt(b-1) == ' ') b--; 
        if (b == 0) return '';
        return str.substr(a,b-a);        
    }
    
    
    /* ==== d2h() =============================== */
    // decimal to hexadecimal conversion
    var hD="0123456789abcdef";
    this.d2h = function (d, bit) {
        var hbit = d & 0x80000000;
        d = d & 0x7fffffff;
        var h = hD.substr(d&15,1);
        while(d>15) {
            d>>=4;
            if (hbit) {
                d |= 0x08000000;
                hbit = 0;
            }
            h=hD.substr(d&15,1)+h;
        }
        if (bit) {
            var p = 2;
            switch(bit) {
            case 16 : p = 4; break;
            case 24 : p = 6; break;
            case 32 : p = 8; break;
            }
            h = this.padl( h, p, '0' );
        }
        return h;
    }
    this.h2d = function(h) {return parseInt(h,16);}
    
    
}
var lib_common = new JLibCommon();


var COLOR_TRANSPARENT = -1;
var INVALID_BUFFER = -1;

/* ============================================== */
/* ==== JLibGfx library ======================= */
/* ============================================== */
function JLibGfx() {

    this.setValueText = function(id, text ) {
		var el = document.getElementById(id);
		if (el) el.value = text;
    }

    /* ==== setBackgroundColor() ===================== */
    this.setBackgroundColor = function(id, color) {
		var el = document.getElementById(id);
		if (el && el.style) {
            if ( typeof(color) == 'number' ) {
                if (color == COLOR_TRANSPARENT)
                    color = '';
                else
                    color = lib_common.d2h(color, 24, '0');
            }
            el.bgColor = color;
        }
    }

    /* ==== setCellImage() ====================== */
	this.setCellImage = function( id, img ) {
		var el = document.getElementById(id);
		if (el) {
            if ( typeof(img) == 'number' ) {
                if (img > 0) img = imgList[img];
                    else img = '';
            }
            if (img == '')
                el.innerHTML = '';
            else
			    el.innerHTML = '<img src="' + img + '">';
		}		
	}

    /* ==== setCellText() ======================= */
	this.setCellText = function( id, msg ) {
		var el = document.getElementById(id);
		if (el) {
            el.innerHTML = msg;
        }
    }


    this.hideCell = function( id ) {
		var el = document.getElementById(id);
		if (el) {
            el.innerHTML = '';
            el.bgColor = '';            
        }
    }
    
		
    /* ==== setBackgroundImage() ================ */    
	this.setBackgroundImage = function ( id, img ) {
		var el = document.getElementById(id);
		if (el && el.style) {
            if ( typeof(img) == 'number' ) {
                if (img > 0) img = imgList[img];
                    else img = '';
            }
			if (img != '') {
                if (img.charAt(0) == '#') img = imgList[img];
    		    el.style.backgroundImage = "url("+img + ")";
            }
			else
				el.style.backgroundImage = "";
		}
	}
}
var lib_gfx = new JLibGfx();


var LAY_DATA   = 1;
var LAY_BUFFER = 2;
var LAY_LEVEL  = 3;

/* ============================================== */
/* ==== JBoard class ============================ */
/* ============================================== */
function JBoard() {

	this.cellw   = 20;
	this.cellh   = 20;
    this.boardw  = 10;
    this.boardh  = 10;
    this.bgId    = 0;
    this.name    = "board";
    this.data    = false;          // runtime data
    this.buffer  = false;        // buffer data
    this.level   = false;         // current level data
    this.history = new Array();
    this.selx    = false;
    this.sely    = false;
    this.cursx   = false;
    this.cursy   = false;
    this.bgcolor = 0xa0a0a0;
    
    var recording = false;
    var bgstatus = false;	// background status ON or OFF
    var fgstatus = false;	// foreground status ON or OFF
    
    this.init = function(name, w, h) {
        this.name = name;
        this.boardw  = w;
        this.boardh = h;
        
    }


    
    /**** setBoardSize() ************************/
    // set/change board size
    this.setBoardSize = function(w, h) {
        var i;
        this.boardw = w;
        this.boardh = h;
        this.level = new Array();
        this.buffer = new Array();
        this.data = new Array();
        for (i = 0; i < w * h; i++) {
            this.level[i] = 0;
            this.buffer[i] = 0;
            this.data[i] = 0;
        }        
    }
    
    this.setCellSize = function(w, h) {
    	this.cellw = w;
    	this.cellh = h;
    }
    
    this.setBgImage = function( imgid ) {
        this.bgId = imgid;
    }
        
    this.undo = function() {
    }
    
    this.redo = function() {
    }
    
    this.beginRec = function() {
    }
    
    this.endRec = function() {
    }
    
    this.flipBoard = function( hflip, vflip, lay ) {    
        var x, y, xx, yy, n;
        var tmp = new Array();
        n = 0;
        for (y = 0; y < this.boardh; y++)
            for (x = 0; x < this.boardw; x++) {
                xx = x;
                yy = y;
                if (hflip) xx = this.boardw - x - 1;
                if (vflip) yy = this.boardh - y - 1;
                tmp[n] = this.getCell( xx, yy, lay );
                n++;
            }        
        n = 0;
        for (y = 0; y < this.boardh; y++)
            for (x = 0; x < this.boardw; x++) {
                this.setCell( tmp[n], x, y, lay );
                n++;
            }
    }

    this.refreshBoard = function(fullrefresh) {
        var x, y;
        for (x = 0; x < this.boardw; x++) 
            for (y = 0; y < this.boardh; y++) {                
                buf = this.getCell( x, y, LAY_BUFFER );
                v =  this.getCell( x, y, LAY_DATA );
                if ( this.jgame && this.jgame.unmapCell ) {
                    v = this.jgame.unmapCell(v, x, y);                    
                }
                if (buf != v || fullrefresh) {
                    this.setCell( v, x, y, LAY_BUFFER );
                    if (v < 0)       
                        lib_gfx.hideCell(this.getCellId(x,y));                    
                    else
                        lib_gfx.setCellImage( this.getCellId(x,y), v );
                    
                }                
            }
    }


    this.hideCells = function() {
        var x, y;
        for (x = 0; x < this.boardw; x++) 
            for (y = 0; y < this.boardh; y++) {
                id = this.getCellId(x,y);
                lib_gfx.hideCell(id);
            }
    }

    /* ==== getCellId() ========================== */
    // return the id tag of a cell
    this.getCellId = function(x, y) {
        return this.name + '_' + x + '_' + y;
    }

    /* ==== setBoardBackground() ================= */
    // change background color of the board
    this.setBoardBackgroundColor = function(color) {
        lib_gfx.setBackgroundColor( this.name, color );
    }

    /* ==== setCellBackground() ================== */
    // change background color of a cell
    this.setCellBackgroundColor = function(x, y, color) {
        lib_gfx.setBackgroundColor( this.getCellId(x,y), color );
    }
    
    /**** setBoardImage() *********************** */
    this.setBoardImage = function( id ) {
        lib_gfx.setBackgroundImage( this.name, id );
    }

    /* ==== writeBoard() ======================== */
    // render the board on the document (document.write())
    this.writeBoard = function () {
        var x, y;
    	document.write('<table cellspacing="0" border="0" cellpadding="0" id="' + this.name + '">');
    	for (y = 0; y < this.boardh; y++) {
    		document.write("<tr>");
    		for (x = 0; x < this.boardw; x++) {
    			var cid = this.getCellId(x,y);
                var siz = 'width="' + this.cellw + '" height="' + this.cellh + '"';
                
    			var s = '<td ' + siz + ' id="' + cid + '" align="center" valign="center" onClick="javascript:CellClickHandler(\'' + this.name + '\',' + x + ',' + y+ ')">';
                
                //if (y == 0 && (x == 2 || x == 3)) alert(s);
                //if (x==0 && y == 0) alert(s);
    			document.write(s);
    			document.write("</td>");                                
    		}
    		document.write("</tr>");
    	}
    	document.write("</table>");    	
        for (x = 0; x < this.boardw; x++)
            for (y = 0; y < this.boardh; y++) {
                //var c = lib_common.rand(0x000000, 0x404040);
                //if ( lib_common.rand(1,2) == 1) this.setCellBackgroundColor(x, y, c);
                this.setCellBackgroundColor(x, y, this.bgcolor);
            }
    }
}

    /**** clearBoard() **************************/
    JBoard.prototype.countTiles = function(tilenum, lay) {
        var arr, i, result;
        result = 0;
        if (! lay) lay = LAY_DATA;
        switch (lay) {
            case LAY_BUFFER : arr = this.buffer; break;
            case LAY_LEVEL  : arr = this.level; break;
            default :
                arr = this.data; 
        }
        for (i=0; i<this.boardw * this.boardh; i++) {
            if (arr[i] == tilenum) result++;            
        }
        return result;
    }

    /**** clearBoard() **************************/
    JBoard.prototype.clearBoard = function(n, lay) {
        var arr, i;
        if (! lay) lay = LAY_DATA;
        switch (lay) {
            case LAY_BUFFER : arr = this.buffer; break;
            case LAY_LEVEL  : arr = this.level; break;
            default :
                arr = this.data; 
        }
        for (i=0; i<this.boardw * this.boardh; i++) {
            arr[i] = n;            
        }
    }
    
    /**** getCell() *****************************/
    JBoard.prototype.getCell = function(x, y, lay) {
        var p = (y * this.boardw) + x;
        if (! lay) lay = LAY_DATA;
        if (lay == LAY_DATA) return this.data[p];
        if (lay == LAY_BUFFER) return this.buffer[p];
        if (lay == LAY_LEVEL) return this.level[p];        
    }
    
    /**** setCell() *****************************/
    JBoard.prototype.setCell = function(v, x, y, lay) {
        var p = (y * this.boardw) + x;
        if (! lay) lay = LAY_DATA;
        if (lay == LAY_DATA) this.data[p] = v;
            else if (lay == LAY_BUFFER) this.buffer[p] = v;
                else if (lay == LAY_LEVEL) this.level[p] = v;        
    }

    /**** copyLayer() ***************************/
    JBoard.prototype.copyLayer = function(srclay, destlay) {
        var x, y;
    	for (y = 0; y < this.boardh; y++) 
    		for (x = 0; x < this.boardw; x++) 
                this.setCell( this.getCell(x, y, srclay), x, y, destlay );
    }
    
    /**** swapCell() ****************************/
    JBoard.prototype.swapCell = function(x1, y1, x2, y2, lay) {
        var a, b;
        a = this.getCell(x1, y1, lay);
        b = this.getCell(x2, y2, lay);
        this.setCell( b, x1, y1, lay );
        this.setCell( a, x2, y2, lay );
    }


function CellClickHandler(xid,x,y) {
    wrapMouseHandler(xid,x,y);
}        



/* GAME STATUS (PREDEFINED AND COMMON) VARIABLES */
var GAMESTATUS_STARTUP   = 0;   // at startup
var GAMESTATUS_INTRO     = 1;   // game intro
var GAMESTATUS_PLAYING   = 2;   // game running
var GAMESTATUS_ANIMATION = 3;   // game animation
var GAMESTATUS_GAMEOVER  = 4;   // game over
var GAMESTATUS_LEVELDONE = 5;   // level completed
var GAMESTATUS_LIFELOST  = 6;   // life lost


var SPRITE_BACKGROUND    = 1 << 0;
var SPRITE_PLAYER        = 1 << 1;
var SPRITE_BLOCK         = 1 << 2;
var SPRITE_MOVEABLE      = 1 << 3;
var SPRITE_VMOVE         = 1 << 4;
var SPRITE_HMOVE         = 1 << 5;
var SPRITE_LONGRUN       = 1 << 6;
var SPRITE_TARGET        = 1 << 7;
var SPRITE_OBJECT        = 1 << 8;
var SPRITE_DOCK          = 1 << 9;

var BT_UP              = 0x1001;
var BT_RIGHT           = 0x1002;
var BT_DOWN            = 0x1003;
var BT_LEFT            = 0x1004;
var BT_FIRE1           = 0x1005;
var BT_FIRE            = BT_FIRE1;
var BT_FIRE2           = 6;
var BT_FIRE3           = 7;
var BT_FIRE4           = 8;
var BT_START           = 9;
var BT_RESET           = 10;
var BT_UNDO            = 11;
var BT_REDO            = 12;
var BT_SAVE            = 13;
var BT_LOAD            = 14;
var BT_HELP            = 15;
var BT_RESUME          = 16;
var BT_START           = 17;
var BT_CURSOR          = 18;

var DIR_UP             = 1;
var DIR_RIGHT          = 2;
var DIR_DOWN           = 3;
var DIR_LEFT           = 4;

var IMG_NONE           = 0;
var IMG_INTRO          = 1;
var IMG_GAMEOVER       = 2;
var IMG_GAMEDONE       = 3;
var IMG_LEVELDONE      = 4;

var PRELOAD_SPLASH     = -1;
var PRELOAD_SPRITE     = -2;

/* ============================================== */
/* ==== JBoardGame class ======================== */
/* ============================================== */
function JBoardGame() {

    /* Private vars
    var variablename = ...
    */
    this.gamestatus = GAMESTATUS_STARTUP;
        
    /* Public vars
    this.variablename = ...
    */
    this.board   = false;
    this.bgcolor = 0xa0a0a0;
    this.boardw  = 20;
    this.boardh  = 10;
    this.spritex;
    this.spritey;
    this.vidw    = 320;
    this.vidh    = 200;
    this.name    = "boardgame";
    this.levels     = new Array();
    this.levelsname = new Array();
    this.levelcount = 0;
    this.currlevel  = 0;
    this.bonusat    = new Array();
    this.bonuslev   = 0;
        
    this.editmode = false;
    
    var bgid      = 0;
    
    /* Private functions
    var privfun = function(...) {...}
    */
        
    /* Privileged methods
    var privmethod = new function(...) { ... }
    */
    this.getStatus = function() { return gamestatus; }
        
    /* ==== writeBoard() ======================== */
    // display the board (document.write ...)
    this.writeBoard = function() {        
        this.board.writeBoard();        
        this.board.setBoardBackgroundColor(this.bgcolor);        
    }
        
    
    /* ==== addLevel() ========================== */
    this.addLevel = function( levelname, leveldata ) {
        this.levelsname[this.levelcount] = levelname;
        this.levels[this.levelcount] = leveldata;
        this.levelcount++;
    }
    

    
    /**** showBackgroundImage() *******************/
    // hide cells and show background image
    this.showBackgroundImage = function( id ) {
        this.board.hideCells();
        this.board.setBoardImage(id);
    }
    
    
    /**** writeCursorKeys() *********************/
    this.writeCursorKeys = function( btmask ) {
        var btup = "<input type=\"BUTTON\" id=\"BTUP\" value=\"^\" onClick=\"javascript:wrapKeyHandler(BT_CURSOR, DIR_UP)\">";
        var btleft = "<input type=\"BUTTON\" id=\"BTLEFT\" value=\"&lt;\" onClick=\"javascript:wrapKeyHandler(BT_CURSOR, DIR_LEFT)\">";
        var btdown = "<input type=\"BUTTON\" id=\"BTDOWN\" value=\"v\" onClick=\"javascript:wrapKeyHandler(BT_CURSOR, DIR_DOWN)\">";
        var btright = "<input type=\"BUTTON\" id=\"BTRIGHT\" value=\"&gt;\" onClick=\"javascript:wrapKeyHandler(BT_CURSOR, DIR_RIGHT)\">";

        document.write('<table cellspacing="0" cellpadding="0" border="0" align="center">');
        document.write('<tr>');
        document.write('<td class="cursc1"></td><td class="cursc2" align="center">' + btup + '</td><td class="cursc3"></td>');
        document.write('</tr>');
        document.write('<tr>');
        document.write('<td class="cursc1" align="right">' + btleft + '</td><td class="cursc2" align="center">' + btdown + '</td><td class="cursc3" align="left">' + btright + '</td>');
        document.write('</tr>');
        document.write('</table>');   
    }
    
    /**** showInfo() ************************/
    this.showInfo = function( num, msg ) {
        lib_gfx.setCellText( "gameinfo" + num, msg );
    }
    

}

/* public methods
Classname.prototype.methodName = function(){...}
*/

/*** preloadImage() *******************************/
JBoardGame.prototype.preloadImage = function ( imgfile, w, h, entry ) {
    if (w == PRELOAD_SPLASH) {
        w = this.boardw * this.spritew;
        h = this.boardh * this.spriteh;
    }
    else {
        if (w == PRELOAD_SPRITE) {
            w = this.spritew;
            h = this.spriteh;
        }   
    }
    if (document.images && w > 0 && h > 0) {
        preload_image[entry] = new Image(w, h);
        preload_image[entry].src = imgfile;
        imgList[entry] = imgfile;
    }
}

JBoardGame.prototype.setBoard = function( aboard ) {
    this.board = aboard;
    this.board.jgame = this;
}

/**** setBoardSize() *****************************/
JBoardGame.prototype.setBoardSize = function(w, h) {
        this.boardw = w;
        this.boardh = h;
        if (this.board) this.board.setBoardSize(w,h);
}

/**** setGameSize() *****************************/
JBoardGame.prototype.setGameSize = function(boardw, boardh, spritew, spriteh) {
    this.setBoardSize(boardw, boardh);
    this.spritew = spritew;
    this.spriteh = spriteh;
    this.board.setCellSize(spritew, spriteh);
}

/**** setupGame() *******************************/
JBoardGame.prototype.setupGame = function() {
}


JBoardGame.prototype.startIntro = function() {
}

/**** keyHandler() ******************************/
JBoardGame.prototype.keyHandler = function(btid, param) {
}

/**** mouseHandler() ****************************/
JBoardGame.prototype.mouseHandler = function(src, x, y) {
}


/**** startGame() *******************************/
JBoardGame.prototype.startGame = function(firstlevel) {
}

JBoardGame.prototype.setStatus = function(st) { 
    if (st != this.gamestatus) {
        var oldst = this.gamestatus;
        this.gamestatus = st;
        this.onStatusChange( oldst, st );
    }
}

JBoardGame.prototype.onStatusChange = function( oldst, newst ) {
    this.refreshButtons();
}

JBoardGame.prototype.refreshButtons = function() {
}

/*
JBoardGame.prototype.focusBoard = function() {    
    var el;
    el = getel( 'btfocus' );
    if (el) { el.focus(); }
}
*/

JBoardGame.prototype.unmapCell = function( v, x, y ) {
    return v;
}

JBoardGame.prototype.getCell = function(x, y, lay) {
    return this.board.getCell(x,y,lay);
}
JBoardGame.prototype.setCell = function(v, x, y, lay) {
    this.board.setCell(v,x,y,lay);
}
JBoardGame.prototype.setBgColor = function(x,y,c) {
    this.board.setCellBackgroundColor(x,y,c);
}

JBoardGame.prototype.showBonus = function() {
    var nb = this.bonusat.length;
    var bl;
    var lev = this.currlevel + 1;
    var ol = this.bonuslev;
    while ((bl = this.bonuslev) < nb) {
        if (lev >= this.bonusat[bl]) {
            this.bonuslev++;
        }
        else
            break;
    }
    if (ol != this.bonuslev) {
        var s = '';
        var el = document.getElementById('ID_BONUS');
        if (el) {
            var i;
            for (i=0; i<this.bonuslev;i++) {
                var p = this.plev(this.bonusat[i]-1);
                if ( this.bonusfile && this.bonusfile[i]) p = this.bonusfile[i];
                var xfile = jsgamebase + jsgamecode +'/bonus/' + p.toLowerCase();
                var lnk = '<a href="' + xfile + '.jpg" target="new">';
                s += '<div style="float: left; width: 130px;">';
                s += lnk + '<img src="' + xfile + '_thumb.jpg" border="0" style="border: 1px solid #404040"></a>';
                s += '<br /><p style="margin: 2px 0px 20px 0px; text-align: center">' + lnk + 'BONUS #' + (i+1) + '</a></p>';
                s += '</div>';
            }
            el.innerHTML = s;
        }    
    }
}

/* prototype properties
Classname.prototype.propertyName = someValue
*/
JBoardGame.prototype.bgid = 0;
JBoardGame.prototype.jgame = 0;

/* static properties
Classname.propertyName = someValue
*/



var currkeyh;       // current key handler
var currmouseh;     // current mouse handler
function wrapKeyHandler(btid, param) {
    if (currkeyh) 
        return currkeyh.keyHandler(btid, param);
    else
        return false;
}

function wrapMouseHandler(src, x, y) {
    if (currmouseh) currmouseh.mouseHandler(src, x, y);
}

/**** enableKeyboardEvents() ********************/
function enableKeyboardEvents() {
	if (document.addEventListener)
        document.addEventListener("keydown", gkeyHandler, true);
	else {
		if (document.captureEvents && self.Event && self.Event.KEYDOWN)
            document.captureEvents(Event.KEYDOWN);
		document.onkeydown = gkeyHandler;
	}
}

/**** keyHandler() ******************************/
function gkeyHandler(e) {
	if (e && e.which) {
		ch=e.which;
		ctrl=((e.ctrlKey) || (e.metaKey) || (e.altKey) || (e.modifiers));
	}
	else if (window.event) {
		ch=window.event.keyCode;
		ctrl= ((window.event.ctrlKey) || (window.event.altKey) || (window.event.metaKey));
	}
	else
     return;
    if (ch > 0) { /*(ch >= 37 && ch <= 40) || ch == 32) {*/
        var btid;
        var cancelevent;
        switch (ch) {
        case 37 :
            btid = BT_LEFT;
            break;
        case 38 :
            btid = BT_UP;
            break;
        case 39 :
            btid = BT_RIGHT;
            break;
        case 40 :
            btid = BT_DOWN;
            break;
        case 17 :
            btid = BT_FIRE1;
            break;
        default :                
            btid = ch;
        }
        cancelevent = wrapKeyHandler( btid, 0 );
        if (cancelevent) {
            if (e && e.stopPropagation) 
                e.stopPropagation();            
            else
                if (window.event) window.event.cancelBubble = true;

            if (e && e.preventDefault)
                e.preventDefault();
            else
                if (window.event) window.event.returnValue = false;            
            /*if (window.event) window.event.keyCode = 0;*/
        }
    }
    return;
}




