/* 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. 
 * 
 * This file is available and licensed under the following license:
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *
 *   * Neither the name of Sun Microsystems nor the names of its contributors 
 *     may be used to endorse or promote products derived from this software 
 *     without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
* Main.fx
 *
 * Created on 7 Mar, 2009, 9:20:41 AM
 */

package sudoku;

import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.stage.Alert;
import sudoku.Button;
import sudoku.DataCell;

/**
 * @author Rakesh Menon
 */

def database = java.util.ResourceBundle.getBundle("sudoku.data");
def random = new java.util.Random();

public class SudokuNode extends CustomNode {
    
    var dataGrid = Group {
    };
    var buttonGrid: Group = Group {
        translateY: bind dataGrid.boundsInLocal.height + 12
        translateX: bind (dataGrid.boundsInLocal.width - buttonGrid.boundsInLocal.width) / 2.0 + 11
    }

    var showHint = false;
    
    public function updateData() {
        
        var index = random.nextInt(100);
        var data = database.getString("data_{index}");
        var sudokuData = data.split(",");

        showHint = false;
        
        index = 0;
        for(cell in dataGrid.content) {
            var dataCell = (cell as DataCell);
            dataCell.reset();
            dataCell.data = Integer.parseInt(sudokuData[index]);
            index++;
        }
        
        var showCount = 60 - random.nextInt(20);
        while (showCount != 0) {
            index = random.nextInt(81);
            var dataCell = (dataGrid.content[index] as DataCell);
            if(not dataCell.show) {
                dataCell.show = true;
                showCount--;
            }
        }

        reset();
    }
    
    public function verifyData() {

        var win = true;
        
        for(cell in dataGrid.content) {
            var dataCell = (cell as DataCell);
            if(not "{dataCell.data}".equals(dataCell.content)) {
                dataCell.error = true;
                win = false;
            }
            if(not dataCell.show) {
                dataCell.show = true;
            }
        }

        if(win) {
            Alert.inform("Sudoku - Result", "Congratulations! You Win!");
        } else {
            Alert.inform("Sudoku - Result", "You Lose! Please try again!");
        }
        
        reset();
    }
    
    public var selDataCell: DataCell;
    function onCellSelect(cell : DataCell) {
        
        if(cell.show) {
            selDataCell = null;
            return;
        }

        reset();
        showButtonHint(cell);
        
        selDataCell = cell;
        cell.selected = true;
    }
    
    function reset() {
        
        // Reset selection
        for(buttonCell in buttonGrid.content) {
            (buttonCell as Button).selected = false;
        }
        for(dataCell in dataGrid.content) {
            (dataCell as DataCell).selected = false;
        }

        selDataCell = null;
    }
    
    public function hint() {
        if(showHint) {
            if(selDataCell != null){
                selDataCell.content = "{selDataCell.data}";
            }
        } else {
            showHint = true;
            if(selDataCell != null){
                showButtonHint(selDataCell);
            }
        }
    }
    
    function showButtonHint(cell : DataCell) {
        
        if(not showHint) {
            return;
        }
        
        // Get Block Details
        var startRow = 0;
        var startCol = 0;
        if(cell.row < 3 and cell.col < 3) {
            startRow = 0;
            startCol = 0;
        } else if(cell.row < 6 and cell.col < 3) {
            startRow = 3;
            startCol = 0;
        } else if(cell.row < 9 and cell.col < 3) {
            startRow = 6;
            startCol = 0;
        } else if(cell.row < 3 and cell.col < 6) {
            startRow = 0;
            startCol = 3;
        } else if(cell.row < 6 and cell.col < 6) {
            startRow = 3;
            startCol = 3;
        } else if(cell.row < 9 and cell.col < 6) {
            startRow = 6;
            startCol = 3;
        } else if(cell.row < 3 and cell.col < 9) {
            startRow = 0;
            startCol = 6;
        } else if(cell.row < 6 and cell.col < 9) {
            startRow = 3;
            startCol = 6;
        } else if(cell.row < 9 and cell.col < 9) {
            startRow = 6;
            startCol = 6;
        }
        
        for(row in [startRow..
            (startRow + 2)]) {
            for(col in [startCol..
                (startCol + 2)]) {
                var dataIndex = row * 9 + col;
                var dataCell = dataGrid.content[dataIndex] as DataCell;
                var buttonCell = (buttonGrid.content[
                dataCell.data - 1] as Button);
                if(not dataCell.show) {
                    buttonCell.selected = true;
                } else {
                    buttonCell.selected = false;
                }
            }
        }
    }

    function createGrid() : Node {
        
        var grid = Group {
            translateX: 1
            translateY: 1
        };
        
        insert
        Rectangle {
            x: 0
            y: 0
            width: 269
            height: 269
            styleClass: "blockRectangle"
        } into grid.content;

        for(i in [1..2]) {
            insert
            Line {
                startX: 3
                startY: i * 90 - 2
                endX: 265
                endY: i * 90 - 4
                styleClass: "blockLine"
            } into grid.content;
            insert
            Line {
                startX: i * 90 - 2
                startY: 3
                endX: i * 90 - 4
                endY: 265
                styleClass: "blockLine"
            } into grid.content;
        }

        return grid;
    }
    
    override function create() : Node {

        blocksMouse = true;
        
        // Sudoku Cells
        for(row in [0..8]) {
            for(col in [0..8]) {
                insert
                DataCell {
                    data: 0
                    row: row
                    col: col
                    onMousePressed: function(e) {
                        onCellSelect(e.node as DataCell);
                    }
                }
                into dataGrid.content;
            }
        }
        
        // Sudoku Buttons
        for(i in [0..8]) {
            insert
            Button {
                data: "{(i + 1)}"
                col: i
                selected: false
                onMousePressed: function(e) {
                    selDataCell.content = "{(e.node as Button).data}";
                }
            } into buttonGrid.content;
        }
        
        // Sudoku Grid
        var grid = createGrid();
        
        Group {
            content: [ grid, dataGrid, buttonGrid ];
        }
    }

    override var onKeyPressed = function( e : KeyEvent ) {

        if(selDataCell == null) {
            return;
        }
        
        if(e.code == KeyCode.VK_1) {
            selDataCell.content = "1";
        } else if(e.code == KeyCode.VK_2) {
            selDataCell.content = "2";
        } else if(e.code == KeyCode.VK_3) {
            selDataCell.content = "3";
        } else if(e.code == KeyCode.VK_4) {
            selDataCell.content = "4";
        } else if(e.code == KeyCode.VK_5) {
            selDataCell.content = "5";
        } else if(e.code == KeyCode.VK_6) {
            selDataCell.content = "6";
        } else if(e.code == KeyCode.VK_7) {
            selDataCell.content = "7";
        } else if(e.code == KeyCode.VK_8) {
            selDataCell.content = "8";
        } else if(e.code == KeyCode.VK_9) {
            selDataCell.content = "9";
        }
    }
}