// ----------------------------------------------------------------------
// File: sudoku.js
// ----------------------------------------------------------------------
// LICENSE
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License (GPL)
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WIthOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// To read the license please visit http://www.gnu.org/copyleft/gpl.html
// ----------------------------------------------------------------------
// Original Author of this file: Curt Timmerman
// Purpose of this file: user functions Sudoku module
// ----------------------------------------------------------------------

/**
 * pnjavascript/sudoku.js
 * 
 * Module user interface
 * 
 * @author      Curt Timmerman
 * @version     0.1
 * @link        http://www.post-nuke.net              PostNuke home page
 * @license     http://www.gnu.org/copyleft/gpl.html  GNU General Public License
 * @package     PostNuke_3rd_party_Modules
 * @subpackage  Sudoku
 *
 */

//------------------------------------------------------------------------------
// set by server:
//  var sudoku_cell_box_id_base     // cell box id
//  var sudoku_cell_val_id_base     // cell input id
//  var sudoku_solution_grid        // 9x9 array puzzle solution
//  var sudoku_solution_string      // 81 char puzzle solution
//  var sudoku_setup_grid           // 9x9 array initial set up
//------------------------------------------------------------------------------

var sudoku_form_grid ;              // 9x9 array form values
var sudoku_form_string ;            // 81 character string
var sudoku_form_backgroundcolor ;
var sudoku_check_points = new Array () ;
var sudoku_help_state = false ;

//------------------------------------------------------------------------------
/**
 * sudoku_form_grid_set
 *
 * Set the form grid array and form grid string to form element value
 *
 * @param integer Row (0-8) of form grid
 * @param integer Column (0-8) of form grid
 *
 */
function sudoku_form_grid_set (row, col)
{
var cell_id = sudoku_cell_val_id_base + row + col ;     // form cell_id (cellnn)
var cell_value = document.getElementById (cell_id).value ; // get cell value
var cell_box_id = sudoku_cell_box_id_base + row + col ; // form cell_style
var cell_box = document.getElementById (cell_box_id) ;  // get cell box

if (cell_value.length < 1)              // make cell_value 1 character long
    {
    cell_value = ' ' ;
    }
else if (cell_value.length > 1)
    {
    cell_value = cell_value.substr(0, 1) ;
    document.getElementById(cell_id).value = cell_value ;
    }

if (cell_value != ' '                   // fix invalid entries
        && (cell_value < '1'       
            || cell_value > '9'))
    {
    cell_value = ' ' ;
    document.getElementById(cell_id).value = '' ;
    }

sudoku_form_grid[row][col] = cell_value ;               // to grid array
sudoku_form_string = sudoku_form_string + cell_value ;  // to string
sudoku_form_backgroundcolor[row][col] = 'transparent' ;

return (cell_value) ;

} // sudoku_form_grid_set //

//------------------------------------------------------------------------------
/**
 * sudoku_form_extract
 *
 * Extract form grid to array and string
 *
 */
function sudoku_form_extract ()
{
var row ;
var col ;

sudoku_form_grid = new Array (9) ;       // 9x9 array
sudoku_form_string = '' ;               // 81 character string
sudoku_form_backgroundcolor = new Array (9) ;  // 9x9 array
for (row = 0 ; row < 9 ; row++)         // make 2 dimentional arrays
    {
    sudoku_form_grid [row] = new Array (9) ;
    sudoku_form_backgroundcolor [row] = new Array (9) ;  // 9x9 array
    }

for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        sudoku_form_grid_set (row, col) ;
        }
    }

} // sudoku_form_extract //

//------------------------------------------------------------------------------
/**
 * sudoku_validate_cell
 *
 * Validate the puzzle grid entered so far
 *
 */
function sudoku_validate_cell (row, col)
{
var ret = false ;
var grid_row ;
var grid_col ;

if (sudoku_form_grid[row][col] == ' ')
    {
    return (false) ;
    }
if (sudoku_setup_grid[row][col] != '')
    {
    return (false) ;
    }

//---- test row cells ----//
for (grid_col = 0 ; grid_col < 9 ; grid_col++)
    {
    if (grid_col == col)
        {
        continue ;
        }
    if (sudoku_form_grid[row][grid_col] == sudoku_form_grid[row][col])
        {
        sudoku_form_backgroundcolor[row][col] = 'pink' ;
//alert ('col') ;
        ret = true ;
        break ;
        }
    }

//---- test column cells ----//
for (grid_row = 0 ; grid_row < 9 ; grid_row++)
    {
    if (grid_row == row)
        {
        continue ;
        }
    if (sudoku_form_grid[grid_row][col] == sudoku_form_grid[row][col])
        {
        sudoku_form_backgroundcolor[row][col] = 'pink' ;
//alert ('row') ;
        ret = true ;
        break ;
        }
    }

//---- test box group ----//
var box_row = row - (row % 3) ;         // box origin
var box_col = col - (col % 3) ;
var row_off ;
var col_off ;

for (row_off = 0 ; row_off < 3 ; row_off++)
    {
    for (col_off = 0 ; col_off < 3 ; col_off++)
        {
        grid_row = box_row + row_off ;
        grid_col = box_col + col_off ;
        if (grid_row == row
                && grid_col == col)
            {
            continue ;
            }
        if (sudoku_form_grid[grid_row][grid_col] == sudoku_form_grid[row][col])
            {
            sudoku_form_backgroundcolor[row][col] = 'pink' ;
//alert ('box') ;
            ret = true ;
            break ;
            }
        }
    }

return (ret) ;

} // sudoku_validate_cell //

//--------------------------------------------------------------------------
/**
 * sudoku_set_form_attributes
 *
 * Set
 *
 */
function sudoku_set_form_attributes ()
{
var row ;
var col ;
var cell_id ;

for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        cell_box_id = sudoku_cell_box_id_base + row + col ; // form cell_box_id
        cell_box = document.getElementById(cell_box_id) ; // get cell_box
        cell_box.style.backgroundColor = sudoku_form_backgroundcolor[row][col] ;
        }
    }

} // sudoku_set_form_attributes //

//--------------------------------------------------------------------------
/**
 * sudoku_validate
 *
 * Validate the puzzle grid entered so far
 *
 */
function sudoku_validate (extended)
{
var row ;
var col ;
var invalid_grid = false ;

sudoku_form_extract () ;

if (sudoku_form_string == sudoku_solution_string)
    {
    confirm (sudoku_puzzle_completed) ;
    return ;
    }

for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        if (sudoku_validate_cell (row, col))
            {
            invalid_grid = true ;
            }
        }
    }

if (invalid_grid || (! extended))
    {
    sudoku_set_form_attributes () ;
    return ;
    }

for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        if (sudoku_form_grid[row][col] == ' ')
            {
            continue ;
            }
        if (sudoku_setup_grid[row][col] != '')
            {
            continue ;
            }
        if (sudoku_form_grid[row][col] != sudoku_solution_grid[row][col])
            {
            sudoku_form_backgroundcolor[row][col] = 'red' ;
            }
        }
    }

sudoku_set_form_attributes () ;

} // sudoku_validate //

//--------------------------------------------------------------------------
/**
 * sudoku_mark
 *
 * Save check point
 *
 */
function sudoku_mark ()
{

sudoku_form_extract () ;

sudoku_check_points.push (sudoku_form_grid) ;

} // sudoku_mark //

//--------------------------------------------------------------------------
/**
 * sudoku_reset
 *
 * Restore check point
 *
 */
function sudoku_reset (pop_check_point)
{

if (sudoku_check_points.length <= 0)
    {
    return ;
    }

if (pop_check_point)
    {
    sudoku_form_grid = sudoku_check_points.pop (sudoku_form_grid) ;
    }
else
    {
    sudoku_form_grid = sudoku_check_points [(sudoku_check_points.length - 1)] ;
    }

for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        if (sudoku_form_grid[row][col] == ' ')
            {
            sudoku_form_grid[row][col] = '' ;
            }
        document.getElementById (sudoku_cell_val_id_base + row + col).value
            = sudoku_form_grid[row][col] ;             // set cell value
        }
    }

sudoku_form_extract () ;
sudoku_set_form_attributes () ;

} // sudoku_reset //

//--------------------------------------------------------------------------
/**
 * sudoku_purge
 *
 * Purge all check points
 *
 */
function sudoku_purge ()
{

if (sudoku_check_points.length <= 0)
    {
    return ;
    }

sudoku_check_points = new Array () ;

} // sudoku_purge //

//--------------------------------------------------------------------------
/**
 * sudoku_restart
 *
 * Restart puzzle
 *
 */
function sudoku_restart ()
{
var row ;
var col ;

for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        doc_cell = document.getElementById
                    (sudoku_cell_val_id_base + row + col) ;
        doc_cell.value = sudoku_setup_grid[row][col] ; // set cell value
        if (sudoku_setup_grid[row][col] >= '1'
                && sudoku_setup_grid[row][col] <= '9')
            {
            doc_cell.style.backgroundImage
                = 'url(modules/Sudoku/pnimages/cellbg9.gif)' ;
            doc_cell.readOnly = true ;
            }
        else
            {
            doc_cell.style.backgroundImage = 'none' ;
            doc_cell.readOnly = false ;
            }
        }
    }

sudoku_form_extract () ;                // reset form
sudoku_set_form_attributes () ;

sudoku_check_points = new Array () ;    // clear check points

} // sudoku_restart //

//--------------------------------------------------------------------------
/**
 * sudoku_new_grid
 *
 * Get new puzzle grid via AJAX
 *
 */
function sudoku_new_grid (xml_grid)
{
var doc_root = xml_grid.documentElement ;
var top_level = doc_root.firstChild ;
var grid_string ;
var starting_grid_string ;
var solution_grid = 
    [
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9)
    ] ;
var setup_grid = 
    [
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9) ,
    new Array(9)
    ] ;
var game_level ;
var info ;
var cell ;
var cell_attr ;
var row ;
var col ;
var idx ;

//while (top_level)
    //{
    //if (top_level.nodeType == 1)
        //{
        //switch (top_level.nodeName)
            //{
            //case 'info' :
                //info = top_level.firstChild ;
                //break ;
            //case 'cells' :
                //cell = top_level.firstChild ;
                //break ;
            //default :
                //break ;
            //}
        //}
    //top_level = top_level.nextSibling ;
    //}

while (top_level)
    {
    if (top_level.nodeType == 1)
        {
        switch (top_level.nodeName)
            {
            case 'gridstring' :
                grid_string = top_level.firstChild.nodeValue ;
                break ;
            case 'startinggridstring' :
                starting_grid_string = top_level.firstChild.nodeValue ;
                break ;
            case 'level' :
                game_level = top_level.firstChild.nodeValue ;
                break ;
            default :
                break ;
            }
        }
    top_level = top_level.nextSibling ;
    }

//for ( ; cell ; cell = cell.nextSibling)
    //{
    //if (cell.nodeType == 1)
        //{
        //cell_attr = cell.attributes ;
        //row = cell_attr.getNamedItem ('row').nodeValue ;
        //col = cell_attr.getNamedItem ('col').nodeValue ;
        //solution_grid[row][col] = cell_attr.getNamedItem ('sol').nodeValue ;
        //if (cell_attr.getNamedItem ('ini'))
            //{
            //setup_grid[row][col] = cell_attr.getNamedItem ('ini').nodeValue ;
            //}
        //else
            //{
            //setup_grid[row][col] = ' ' ;
            //}
        //}
    //}

idx = 0 ;
for (row = 0 ; row < 9 ; row++)
    {
    for (col = 0 ; col < 9 ; col++)
        {
        solution_grid[row][col] = grid_string.substr (idx, 1) ;
        setup_grid[row][col] = starting_grid_string.substr (idx, 1) ;
        if (setup_grid[row][col] < '1' || setup_grid[row][col] > '9')
            {
            setup_grid[row][col] = '' ;
            }
        idx++ ;
        }
    }

sudoku_solution_grid = solution_grid ;
sudoku_solution_string = grid_string ;
sudoku_setup_grid = setup_grid ;

var heading = document.getElementById('sudoku_heading') ;
heading.innerHTML = 'Sudoku (' + game_level + ')' ;

sudoku_restart () ;

} // sudoku_new_grid //

//--------------------------------------------------------------------------
/**
 * sudoku_newpuzzle
 *
 * Get new puzzle grid via AJAX
 *
 */
function sudoku_newpuzzle (level)
{

Sudoku_getDataReturnXml
    ('index.php?module=Sudoku&action=newpuzzle&level=' + level ,
    sudoku_new_grid) ;

} // sudoku_newpuzzle //

//--------------------------------------------------------------------------
/**
 * sudoku_toggle_help
 *
 * Toggle help visibility
 *
 */
function sudoku_toggle_help ()
{
var obj = document.layers ? document.layers['sudoku_help'] :
    document.getElementById ?  document.getElementById('sudoku_help').style :
    document.all['sudoku_help'].style ;

sudoku_help_state = (! sudoku_help_state) ;
    //{
    //sudoku_help_state = false ;
    //}
//else
    //{
    //sudoku_help_state = true ;
    //}

obj.visibility = document.layers ? (sudoku_help_state ? "show" : "hide") :
   (sudoku_help_state ? "visible" : "hidden");

} // sudoku_toggle_help //

