/* ==========================================================================
 * clMemoryGame.js
 *
 * Written by Kostas Symeonidis
 * Copyright (c) 2009, CyLog Software
 * ==========================================================================
 * History:
 *
 * 11.Oct.2009  Created library for new round of CyLog games
 * ==========================================================================
 *
 * ==========================================================================
 */

// ==========================================================================

// ---- Constants -----------------------------------------------------------

var MAX_IMAGES = 36;
var IMG_CLOSED = 99;

var imgclosed = new Image(90, 60);
imgclosed.src = "/static/games/memimg/closed.png";

// ---- Global Variables ----------------------------------------------------

var imgs = new Array();
var imgCount = 0;

// ---- Global initialisation -----------------------------------------------

var imgsFname = new Array();

var tiles = new Array();  // the actual tiles of the board
var sig = new Array();    // the signature of the solution gradually being built

var o1 = IMG_CLOSED;
var o2 = IMG_CLOSED;
var state = 0;
var score = 0;
var visible = 0;
var gameStarted = false;
var starttime;
var prevtime;
var endtime;

var lblScore;     // label for displaying current score
var lblTime;      // displays the time
var edtScore;     // hidden form element to submit the score
var edtDuration;  // hidden form element to submit the duration
var edtSig;       // hidden form element to submit the signature
var ajaxMsg;      // ajax keep alive message

var signature;   // being built up as we reveal cards 

/*
 * Returns the current time in milliseconds
 */
function timeInMillis ()
{
    var now = new Date();
    return now.getTime();
}

/*
 * Gets the MAX_IMAGES filenames and mixes them up 100 times
 */
function randomMixUpImageFilenames ()
{
    // setup all the image filenames
    for (var i = 0; i < MAX_IMAGES; i++)
    {
        imgsFname[i] = lPadZero(i, 2) + ".png";
    }

    var h1,h2,h3;
    for (i = 0; i < 300; i++)
    {
        h1 = Math.floor(Math.random() * MAX_IMAGES);
        h2 = Math.floor(Math.random() * MAX_IMAGES);
        if (h1 != h2)
        {
            h3 = imgsFname[h1];
            imgsFname[h1] = imgsFname[h2];
            imgsFname[h2] = h3;
        }
    }
}

/*
 * Sets up a Memory game for the given Rows and Columns
 */
function setupMemoryGame ( a_iRows, a_iCols )
{
    imgCount = a_iRows * a_iCols;

    randomMixUpImageFilenames();
    for (var i = 0; i < imgCount; i++)
    {
        imgs[i] = new Image(90, 60);
        imgs[i].src = "/static/games/memimg/" + imgsFname[i];
    }

    var h = 0;

    for (i = 0; i < imgCount; i++)
    {
        tiles[i] = IMG_CLOSED;
        sig[i] = IMG_CLOSED;
    }
    for (i = 0; i < imgCount / 2; i++)
    {
        for (var j = 0; j < 2; j++)
        {
            do {
                h = Math.round(Math.random() * imgCount);
                if (h == imgCount)
                    h = 0;
            }
            while (tiles[h] != IMG_CLOSED);
            tiles[h] = i;
        }
    }

    // page placeholders that will be updating
    lblScore = document.getElementById("lblScore").firstChild;
    lblTime = document.getElementById("lblTime").firstChild;
    edtScore = document.getElementById("edtScore");
    edtDuration = document.getElementById("edtDuration");
    edtSig = document.getElementById("edtSig");

    ajaxMsg = document.getElementById("ajaxMsg");

    // start score
    score = 0;

    /*
    var s = "";
    for (i = 0; i < imgCount; i++)
    {
        if (i != 0)
            s += ", ";
        s += tiles[i] + "-" + imgsFname[tiles[i]].substr(0, 2);
    }
    edtSig.value = "[" + s + "]";
    */
}

function buildSignature ()
{
    var s = "";
    for (var i = 0; i < imgCount; i++)
    {
        if (i != 0)
            s += ", ";
        s += sig[i] + "-" + imgsFname[sig[i]].substr(0, 2);
    }
    edtSig.value = s;
}

function hideimages ()
{
    document.images["bb" + o1].src = imgclosed.src;
    document.images["bb" + o2].src = imgclosed.src;
    state = 0;
}

function imageClick ( btn )
{
    if (!gameStarted)
    {
        gameStarted = true;
        starttime = timeInMillis();
        setInterval("displayTime()", 1000);
    }

    if ((tiles[btn] != IMG_CLOSED ) && (state != 2))
    {
        // do Ajax call
        ajaxMsg.value = btn + "-" + tiles[btn];
        invoke($('form')[1], 'ajax', '#replaceWithAjax');

        // increase state (how many images are open)
        state++;
        if (state == 1)
        {
            o1 = btn;
            document.images["bb" + btn].src = imgs[tiles[btn]].src;
        }
        if (state == 2)
        {
            if (btn == o1)
            {
                state = 1;
                return;
            }

            score++;
            lblScore.nodeValue = score;

            o2 = btn;
            document.images["bb" + btn].src = imgs[tiles[btn]].src;
            if (tiles[o1] == tiles[o2])
            {
                sig[o1] = tiles[o1];
                sig[o2] = tiles[o2];
                tiles[o1] = IMG_CLOSED;
                tiles[o2] = IMG_CLOSED;
                state = 0;
                visible += 2;
                if (visible == imgCount)
                {
                    endtime = timeInMillis();
                    gameStarted = false;
                    edtScore.value = score;
                    edtDuration.value = endtime - starttime;
                    buildSignature();

                    // Now submit the form
                    submit();
                }
            }
            else
            {
                setTimeout("hideimages()", 1000);
            }
        }
    }
}

/*
 * Displays the running clock at the HTML node with id "lblTime" 
 */
function displayTime ()
{
    if (gameStarted)
    {
        var timeElapsed = (timeInMillis() - starttime) / 1000;
        var minutes = Math.floor(timeElapsed / 60);
        var seconds = Math.floor(timeElapsed % 60);

        lblTime.nodeValue = lPadZero(minutes, 2) + ":" + lPadZero(seconds, 2);
    }
    else
    {
        timeElapsed = (endtime - starttime);
        minutes = Math.floor(timeElapsed / 60000);
        seconds = Math.floor(timeElapsed / 1000) % 60;
        var millis = Math.floor(timeElapsed % 1000);
        lblTime.nodeValue = lPadZero(minutes, 2) + ":" + lPadZero(seconds, 2) + "." + lPadZero(millis, 3);
    }
}

function submit ()
{
    document.forms[0].submit();
}

