﻿//*****************************************************************************
//
//    ChessDoku puzzle classes & methods 
//    (c) 2009 The Software Department Ltd. 
//
//*****************************************************************************

//*****************************************************************************
// Timer Class
//
// Constructor. ***************************************************************
function Timer(clock, me) 
{
    this.clock = clock;
    
    this.elapsedTime = 0.0;
    this.running = false;
    
    this.callback = me + ".update()";
    this.interval = null;

}
// Start. *********************************************************************
Timer.prototype.start = function () 
{
    this.startDate = new Date();
    this.running = true;
    this.interval = window.setInterval(this.callback, 1000);
}
// Stop. **********************************************************************
Timer.prototype.stop = function (reset)
{
    this.update();
    if (reset)
    {
        this.elapsedTime=0.0;
        this.refreshClock();
    }
    this.running = false;
    window.clearInterval(this.interval);
}
// Update. ********************************************************************
Timer.prototype.update = function ()
{
    this.elapsedTime = ((new Date()) - this.startDate)/1000;
    this.refreshClock();
}
Timer.prototype.refreshClock = function ()
{
    // Format time display
    var diff = this.elapsedTime;
    var hours = Math.floor(diff / 3600);
    diff -= hours * 3600;
    var mins = Math.floor(diff / 60);
    diff -= mins * 60;
    var secs = Math.round(diff, 0);
        
    var strhours = (hours < 10 ? "0" + hours : hours);
    var strmins = (mins < 10 ? "0" + mins : mins);
    var strsecs = (secs < 10 ? "0" + secs : secs);

    strhours = "<span class='clockdigits'>" + strhours + "</span>";
    strmins = "<span class='clockdigits'>" + strmins + "</span>";
    strsecs = "<span class='clockdigits'>" + strsecs + "</span>";
              
    this.clock.innerHTML = strhours + ":" + strmins + ":" + strsecs;
}
//*****************************************************************************
// Pieces Class
//
// Constructor. ***************************************************************
function Pieces()
{
    this["WK"] = "White King";
    this["WQ"] = "White Queen";
    this["WB"] = "White Bishop";
    this["WR"] = "White Rook";
    this["WN"] = "White Knight";
    this["WP"] = "White Pawn";
    this["BK"] = "Black King";
    this["BQ"] = "Black Queen";
    this["BB"] = "Black Bishop";
    this["BR"] = "Black Rook";
    this["BN"] = "Black Knight";
    this["BP"] = "Black Pawn";
    this["ST"] = "Start Tool";
    this["HT"] = "Hint Tool";
    
}

//*****************************************************************************
// Game Class
//
// Constructor. ***************************************************************
function Game(options, me)
{

    this.options = options;
    switch (options.type)
    {
        case "4x4":
            this.gridSize=4;
            break;
        case "6x6":
            this.gridSize=6;
            break;    
        default:
            this.gridSize=9;
            break;    
    }
    

    /* Initialise the playing pieces */
    this.pieceNames = new Pieces();

    var temp = (new String(options.pieces)).split("|");
    var maxPieces = temp.length;
    
    this.pieces = [];
    for (var i=0; i<maxPieces; i++)
    {
        var code = temp[i];
        this.pieces[i] = {};
        this.pieces[i].code = temp[i];
        this.pieces[i].elem = document.getElementById("pc_" + i);
        this.pieces[i].elem.src = "images/" + temp[i] + ".gif";
        this.pieces[i].elem.alt = this.pieceNames[temp[i]];
        this.pieces[i].elem.title = this.pieceNames[temp[i]];
    }
    
    this.blank = "images/blank.gif";

    // Initialise the board
    this.board = {};

    var temp = (new String(options.start)).split("|");
    var maxSquares = temp.length;

    this.board.squares=[];
    for (var i=0; i<maxSquares; i++)
    {
        this.board.squares[i] = document.getElementById("sq_"+i);
    }
    
    // Initialise the timer and game params 
    this.timer = new Timer(document.getElementById("clock"), me + ".timer");
    
    this.selectedPiece = 0;
    this.hintUsed = false;

    // Initialse the message area and buttons
    this.messageHolder = document.getElementById(options.msgfield);
//    this.messageHolder.parentElement.onclick = function() {return eval(me + ".clearMessage();");}
    this.messageHolder.parentNode.onclick = function() {return eval(me + ".clearMessage();");}
    
    this.startBtn = document.getElementById(options.startbtn);
    this.startBtn.onclick = function() {return eval(me + ".start();");}
    this.startBtn.disabled = false;

    this.hintBtn = document.getElementById(options.hintbtn);
    this.hintBtn.onclick = function() {return eval(me + ".hint();");}
    this.hintBtn.disabled = true;

    this.finishBtn = document.getElementById(options.finishbtn);
    this.finishBtn.onclick = function() {return eval(me + ".finish();");}
    this.finishBtn.disabled = true;

    this.quitBtn = document.getElementById(options.quitbtn);
    this.quitBtn.onclick = function() {return eval(me + ".quit('"+ options.type + "');");}
    this.quitBtn.disabled = false;

    // Set up keep-alive to prevent session timeout (ten minutes)
    window.setInterval(me + ".keepAlive();", (1000*60*10)); 

    // Record the CheckSolution delegate and initialise status
    this.checkSolution = eval(options.checkproxy);

    this.status = "stopped";
}
// Start. ************************************************************
Game.prototype.start = function () {
     	
    // Clear message
    this.clearMessage();
     	
    // Initialise selection (from start position)
    this.selection = (new String(options.start)).split("|");
    var maxSquares = this.selection.length;

    for (var i=0; i<maxSquares; i++)
    {
        if (this.selection[i])
        {
            this.board.squares[i].src = "images/" + this.selection[i] + ".gif";
            this.board.squares[i].className="presquare";
        }        
    }

	// Select first piece.
    this.status = "running";
	this.selectPiece(0);
	
	// Set button state 
	this.checkStatus();
	
	// Start timer
	this.timer.start();
}

// Hint. ************************************************************
Game.prototype.hint = function () {

    // Show hint
    if (!this.hintUsed)
    {
        var temp = (new String(this.options.hint)).split("|");
        var maxSquares = temp.length;

        for (var i=0; i<maxSquares; i++)
        {
            if (temp[i])
            {
                this.selection[i] = temp[i];
                this.board.squares[i].src = "images/" + temp[i] + ".gif";
                this.board.squares[i].className="hintsquare";
            }        
        }

    	// Disable button
	    this.hintUsed = true;
        this.hintBtn.disabled = true;
    }
}

// Finish. ********************************************************************
Game.prototype.finish = function () 
{
    // Check solution
    var puzzleId = this.options.id;
    var memberId = this.options.memberid;
    var attempt = this.selection.join("|");
    var score = this.timer.elapsedTime;
    
    var userContext = this;
    
    this.checkSolution(puzzleId, memberId, attempt, score, this.solutionChecked, null, userContext, null);
   
}

// Solution Checked. **********************************************************
Game.prototype.solutionChecked = function(result, userContext)
{
    var results = result.split("|");
    
    userContext.message(results[1]);
    if (results[0] == "1") userContext.stop();
}

// Check game status. *********************************************************
Game.prototype.checkStatus = function ()
{
    switch (this.status)
    {
        case "not started":
            this.startBtn.disabled = false;
            this.hintBtn.disabled = true;
            this.finishBtn.disabled = true;
            break;
            
        case "running":
            // Reset button states
            this.startBtn.disabled = true;
            this.hintBtn.disabled = this.hintUsed;
            this.finishBtn.disabled = false;
            break;
            
        case "stopped":
            this.startBtn.disabled = true;
            this.hintBtn.disabled = true;
            this.finishBtn.disabled = true;
            break;
            
        default:
            break;
    }
}
// Stop. **********************************************************************
Game.prototype.stop = function ()
{
        this.status = "stopped";
        this.timer.stop(true);
        this.checkStatus();
}
// Select Piece. **************************************************************
Game.prototype.selectPiece = function (piece) 
{

    if (this.status == "running")
    {
        try {
            this.pieces[this.selectedPiece].elem.className = "piecenormal";
            this.pieces[piece].elem.className = "pieceselected";
            this.selectedPiece = piece;
        
            window.status = "Click board to place " + this.pieces[piece].elem.alt;
        }
        catch (ex)
        {
            // Do nothing. Index out of range??
        }
        
    } else {
        this.message("Please start the game before making selections.", true); 
    }        
}

// Set Piece. *****************************************************************
Game.prototype.setPiece = function (square){

    if (this.status == "running"){
        try {
            // If the target square is a start square or hint do nothing.
            var temp = this.board.squares[square].className;
            if (temp == "hintsquare" || temp == "presquare") return;

            // If selected piece is already in target square, remove it, 
            // otherwise add it. 
            var piece = this.pieces[this.selectedPiece].code;
            if (piece == this.selection[square]) {
                // Remove
                this.selection[square] = "";
                this.board.squares[square].src = this.blank;
            }
            else
            {
                // Add 
                this.selection[square] = piece;
                this.board.squares[square].src = this.pieces[this.selectedPiece].elem.src;
                
            }
        }
        catch (ex)
        {
            // Do nothing. Index out of range??
        }

    } else {
        this.message("Please start the game before making selections.", true); 
    }        
}

// Redirect. ******************************************************************
Game.prototype.quit = function (tab)
{    
    if (this.options.memberid == 0) 
    {
        document.location = "default.aspx?t=" + tab;
    }
    else
    {
        document.location = "my-chessdoku.aspx?t=" + tab;
    }
}

// Message. *******************************************************************
Game.prototype.message = function (message, warn){    
//    this.messageHolder.parentElement.style.display="inline";
    this.messageHolder.parentNode.style.display="inline";
    this.messageHolder.innerHTML = message; 
    if (warn) 
    {
            this.messageHolder.className="warnmsg";  
    }
    else
    {
            this.messageHolder.className="normmsg";  
    }
}

// Clear Message. *************************************************************
Game.prototype.clearMessage = function (){  
//        this.messageHolder.parentElement.style.display="none";
        this.messageHolder.parentNode.style.display="none";
        this.messageHolder.innerHTML = "";   
   
}

// Keep Alive. ****************************************************************
Game.prototype.keepAlive = function (){  
    var img = new Image(1,1);
    var server = document.location.protocol + "//" + document.location.host;
    img.src = server + '/keep-alive.aspx';  
}

//*****************************************************************************
// Editor Class
//
// Constructor. ***************************************************************
function Editor(options, me)
{

    this.options = options;
    switch (options.type)
    {
        case "4x4":
            this.gridSize=4;
            this.quit = function () {window.location.replace("admin.aspx?t=4x4");}
            break;
        case "6x6":
            this.gridSize=6;
            this.quit = function () {window.location.replace("admin.aspx?t=6x6");}
            break;    
        default:
            this.gridSize=9;
            this.quit = function () {window.location.replace("admin.aspx?t=9x9");}
            break;    
    }
    
    
    /* Initialise the playing pieces and show the (normally hidden) start and 
      hint tools */
    this.startTool = "ST";
    this.hintTool = "HT";

    this.pieceNames = new Pieces();

    var temp = (new String(options.pieces + "|" + this.startTool + "|" + this.hintTool)).split("|");
    var maxPieces = temp.length;
    
    this.pieces = [];
    for (var i=0; i<maxPieces; i++)
    {
        var code = temp[i];
        this.pieces[i] = {};
        this.pieces[i].code = temp[i];
        this.pieces[i].elem = document.getElementById("pc_" + i);
        this.pieces[i].elem.src = "images/" + temp[i] + ".gif";
        this.pieces[i].elem.alt = this.pieceNames[temp[i]];
        this.pieces[i].elem.title = this.pieceNames[temp[i]];
    }
    
    this.pieces[maxPieces-2].elem.parentNode.style.display="inline";
    this.pieces[maxPieces-1].elem.parentNode.style.display="inline";
    
    this.blank = "images/blank.gif";

    // Initialise the board
    this.board = {};

    var temp = (new String(options.start)).split("|");
    var maxSquares = temp.length;

    this.board.squares=[];
    for (var i=0; i<maxSquares; i++)
    {
        this.board.squares[i] = document.getElementById("sq_"+i);
    }

    this.selectedPiece = 0;

    // Initialse the message area and buttons
    this.messageHolder = document.getElementById(options.msgfield);
    this.messageHolder.parentNode.onclick = function() {return eval(me + ".clearMessage();");}

    this.startBtn = document.getElementById(options.startbtn);
    this.startBtn.onclick = function() {return null;}
    this.startBtn.disabled = true;

    this.hintBtn = document.getElementById(options.hintbtn);
    this.hintBtn.onclick = function() {return null;}
    this.hintBtn.disabled = true;

    this.finishBtn = document.getElementById(options.finishbtn);
    this.finishBtn.value="Save";
    this.finishBtn.onclick = function() {return eval(me + ".save();");}
    this.finishBtn.disabled = false;

    this.quitBtn = document.getElementById(options.quitbtn);
    this.quitBtn.onclick = function() {return eval(me + ".quit();");}
    this.quitBtn.disabled = false;

    // Initialise the publish field
    this.pubField = document.getElementById(options.pubfield);
    this.pubField.checked = options.publish==1;
    
    // Record the SaveSolution delegate
    this.saveSolution = eval(options.updtproxy);
    
    // Initailaise the pieces
    this.start();
    
    // Set up keep-alive to prevent session timeout (ten minutes)
    window.setInterval(me + ".keepAlive();", (1000*60*10)); 
}
// Start. ************************************************************
Editor.prototype.start = function () {
     	
    // Clear message
    this.clearMessage();
     	
    // Initialise selection (from solution)
    this.selection = (new String(options.solution)).split("|");
    var maxSquares = this.selection.length;

    for (var i=0; i<maxSquares; i++)
    {
        if (this.selection[i])
        {
            this.board.squares[i].src = "images/" + this.selection[i] + ".gif";
        }        
    }

    // Initialise start pieces
    var temp = (new String(options.start)).split("|");
    var maxSquares = temp.length;

    for (var i=0; i<maxSquares; i++)
    {
        if (temp[i])
        {
            this.board.squares[i].src = "images/" + temp[i] + ".gif";
            this.board.squares[i].className="presquare";
        }        
    }

    // Initialise hints
    var temp = (new String(options.hint)).split("|");
    var maxSquares = temp.length;

    for (var i=0; i<maxSquares; i++)
    {
        if (temp[i])
        {
            this.board.squares[i].src = "images/" + temp[i] + ".gif";
            this.board.squares[i].className="hintsquare";
        }        
    }

	// Select first piece.
	this.selectPiece(0);
	
}

// Hint. ************************************************************
Editor.prototype.hint = function () {
    // Not required.
}

// Save. ********************************************************************
Editor.prototype.save = function () 
{
    // Save solution
    var id = this.options.id;
    var puzzleTypeCode = this.options.type;
    
    var temp = (new String(options.start)).split("|");
    for (var i=0; i < temp.length; i++)
    {
        temp[i] = (this.board.squares[i].className=="presquare")? this.selection[i]:"";
    }
    var start = temp.join("|");
    
    var temp = (new String(options.hint)).split("|");
    for (var i=0; i < temp.length; i++)
    {
        temp[i] = (this.board.squares[i].className=="hintsquare")? this.selection[i]:"";
    }
    var hint = temp.join("|");
    
    var solution = this.selection.join("|");
    var publish = this.pubField.checked? "1":"0";
    
    var userContext = this;
    
    this.saveSolution(id, puzzleTypeCode, start, hint, solution, publish, this.solutionSaved, null, userContext, null);
   
}

// Solution Checked. **********************************************************
Editor.prototype.solutionSaved = function(result, userContext)
{
    var results = result.split("|");
    if (results[0]==1)
    {
        // Success
        if (userContext.options.id==0) userContext.options.id = results[1]; // Capture id if new.
        userContext.message(results[2]);
    }
    else
    {
        userContext.message(results[1]);
    }
}

// Select Piece. **************************************************************
Editor.prototype.selectPiece = function (piece) 
{

    try 
    {
        this.pieces[this.selectedPiece].elem.className = "piecenormal";
        this.pieces[piece].elem.className = "pieceselected";
        this.selectedPiece = piece;
    
        window.status = "Click board to place " + this.pieces[piece].elem.alt;
    }
    catch (ex)
    {
        // Do nothing. Index out of range??
    }
      
}

// Set Piece. *****************************************************************
Editor.prototype.setPiece = function (square){

    try 
    {

        // If selected piece is a tool, mark relevant square. If it is already
        // in target square, remove it, otherwise add it. 
        var piece = this.pieces[this.selectedPiece].code;
        if (piece == this.startTool)
        {
            this.board.squares[square].className= (this.board.squares[square].className=="presquare")? "square":"presquare";
        }
        else if (piece == this.hintTool)
        {
            this.board.squares[square].className= (this.board.squares[square].className=="hintsquare")? "square":"hintsquare";
        }
        else if (piece == this.selection[square]) 
        {
            // Remove
            this.selection[square] = "";
            this.board.squares[square].src = this.blank;
        }
        else
        {
            // Add 
            this.selection[square] = piece;
            this.board.squares[square].src = this.pieces[this.selectedPiece].elem.src;
            
        }
    }
    catch (ex)
    {
        // Do nothing. Index out of range??
    }
}

// Message. *******************************************************************
Editor.prototype.message = function (message, warn){    
    this.messageHolder.parentNode.style.display="inline";
    this.messageHolder.innerHTML = message; 
    if (warn) 
    {
            this.messageHolder.className="warnmsg";  
    }
    else
    {
            this.messageHolder.className="normmsg";  
    }
}

// Clear Message. *****************************************************************
Editor.prototype.clearMessage = function (){  
        this.messageHolder.parentNode.style.display="none";
        this.messageHolder.innerHTML = "";   
   
}

// Keep Alive. ****************************************************************
Editor.prototype.keepAlive = function (){  
    var img = new Image(1,1);
    var server = document.location.protocol + "//" + document.location.host;
    img.src = server + '/keep-alive.aspx';  
}


//*****************************************************************************
// Game List Class
//
// Constructor. ***************************************************************
function GameList(options)
{
    this.options = options;

    switch (options.type)
    {
        case "4x4":
            break;
        case "6x6":
            break;    
        default:
            break;    
    }
    
    this.activeBoard = null;
    
}
// Show (Leader) Board. *******************************************************
GameList.prototype.showBoard = function (id) {

    this.hideBoard();
    
    try 
    {

        var board = document.getElementById(id);
        var parent = board.parentNode;

        board.style.display = "block";
        this.activeBoard = board;
    }
    catch (ex)
    {
    }
}

// Start. *********************************************************************
GameList.prototype.hideBoard = function () {
    if (this.activeBoard)
    {
        this.activeBoard.style.display = "none";
        this.activeBoard = null;
    }
}

//*******************************************************************
// Member List Class
//
// Constructor. ***************************************************************
function MemberList(options)
{
    this.options = options;

    this.activeBoard = null;
    
}
// Show (Leader) Board. *******************************************************
MemberList.prototype.showBoard = function (id) {

    this.hideBoard();
    
    try 
    {

        var board = document.getElementById(id);
        var parent = board.parentElement;

        //board.style.top = 20;
        //board.style.left = 100;
        board.style.display = "block";
        this.activeBoard = board;
    }
    catch (ex)
    {
    }
}

// Start. *********************************************************************
MemberList.prototype.hideBoard = function () {
    if (this.activeBoard)
    {
        this.activeBoard.style.display = "none";
        this.activeBoard = null;
    }
}



