all  = '123456789';
bad =  new Array();
path = '';


/**
 * Set by gwt on moduleLoad
 */
var gwtsudoku = null;

function removeElement( c, s ) {
    var p = s.indexOf(c)
    if( p != -1 ) {
        return s.substring(0, p) + s.substring(p+1);
    }

    return s;
}

function SudokuBoard(noElement, laticeSize) {


}


SudokuBoard.prototype.setValueForElement = function(x, y, value ) {
    this.history[this.history.size()]  =  this.elements[x][y];
    // this.elements[x][y].valueSet = ;
}


SudokuBoard.prototype.init = function() {
    all  = '123456789';
    bad =  new Array();
    path = '';

    this.w = 51;
    this.h = 51;

//    this.level = 0;
//    this.numberToHide = 1;

    this.finishTime = null;
    this.startTime = null;

    this.boardPointerX = 0;
    this.boardPointerY = 0;
    this.boardPointer = null;

    this.history = Array();
    this.gameStatus = Array();

    /* all element which user can see */
    this.elements = new Array();

    /* from which player can take elements */
    this.blocks   = new Array();

    for( x = 0; x < 9; x++ ) {
        this.elements[x] = new Array();
        for(y = 0; y < 9; y++ ) {
            deltaY = Math.floor((y)/3) * 10;
            deltaX = Math.floor((x)/3) * 10;
            this.elements[x][y] = {

                    /* value set by player in current game */
                    startValue: null,
                    /*  ??? */
                    value: null,
                    /* value from board generator */
                    valueSet: null,
                    /* ??? */
                    bid: null, 'x': x, 'y': y,
                    'left' : deltaX+x*this.w, 'top': deltaY + y *this.h,
                    'w' : this.w, 'h': this.h,
                    'id':  'a'+(x+1)+(y+1),

                    possible: new Array(), showPossible: false

                    };



        }
    }


    l = 0;
    t = 0;
    for( x = 0; x < 3; x++ ) {
        for( y = 0; y < 3; y++ ) {
            i  = 1+ x+y*3;
            this.blocks[i] = { bid: i, styleForBlock: 'klocek'+i, 'left': l + this.w * x, 'top':  t + this.h * y }

        }
    }



}

SudokuBoard.prototype.movePointer = function ( p_arrowCode ) {

    var nX = this.boardPointerX;
    var nY = this.boardPointerY;

    var run =  true;
    var found =  false;

    while(  run ) {
        switch( p_arrowCode ) {
        case ARROW_LEFT:
            nX -= 1;
            break;
        case ARROW_RIGHT:
            nX += 1;
            break;
        case ARROW_UP:
            nY -= 1;
            break;
        case ARROW_DOWN:
            nY += 1;
            break;
        }

        if( nX < 0 ) {
            nX  = 8; // TODO remove hardcoded 8
        }
        if( nX > 8 ) {
            nX  = 0; // TODO remove hardcoded 8
        }
        if( nY < 0 ) {
            nY  = 8; // TODO remove hardcoded 8
        }
        if( nY > 8 ) {
            nY  = 0; // TODO remove hardcoded 8
        }

        run = false;
        found = true;
    }
    this.boardPointerX = nX;
    this.boardPointerY = nY;

    return found;
}


/**
 * Return true if p_keyCode is key which corrresponds to digit (in Sudoku 9x9)
 */
SudokuBoard.prototype.isBoardKey = function ( p_keyCode) {
    if( p_keyCode >= 0 && p_keyCode <= 9  ) {
        return true;
    }
    else {
        return false;
    }

}

SudokuBoard.prototype.rebuildElementsFromPath = function ( p, b ) {
    var x, y, s, l, c, i, tx, ty;

    for( x = 0; x < 9; x++ ) {
        // this.elements[x] = new Array();
        for(y = 0; y < 9; y++ ) {
            this.elements[x][y].value = all;
        }
    }

    i = 0;
    mainLoop:
        for( x = 0; x < 9; x++ ) {
            for(y = 0; y < 9; y++ ) {
                s = this.elements[x][y].value;

                // till we rich end of path
                if( i >= p.length ) {
                    break mainLoop;
                }
                c = p.charAt(i);
                i++;

                this.elements[x][y].value = " ";


                for( j = 0; j < 9; j++ ) {
                    this.elements[j][y].value = removeElement(c, this.elements[j][y].value);
                    this.elements[x][j].value = removeElement(c, this.elements[x][j].value);
                }

                tx = 3*Math.floor(x/3);
                ty = 3*Math.floor(y/3);
                for( xx = 0; xx < 3; xx++ ) {
                    for( yy = 0; yy < 3; yy++ ) {
                        this.elements[xx+tx][yy+ty].value = removeElement(c, this.elements[xx+tx][yy+ty].value);
                    }
                }

                this.elements[x][y].value = c;
            }

        }

    if( b.length > 0 ) {
        var s = this.elements[x][y].value;
        for( i = 0; i< b.length; i++ ) {
            s = removeElement( b.charAt(i), s );
        }
        this.elements[x][y].value = s;
    }
}


SudokuBoard.prototype.clearElementsForElement =  function (c, x, y) {
    try {
        this.elements[x][y].value = " ";

        for( j = 0; j < 9; j++ ) {
            this.elements[j][y].value = removeElement(c, this.elements[j][y].value);
            this.elements[x][j].value = removeElement(c, this.elements[x][j].value);
        }

        tx = 3*Math.floor(x/3);
        ty = 3*Math.floor(y/3);
        for( xx = 0; xx < 3; xx++ ) {
            for( yy = 0; yy < 3; yy++ ) {
                this.elements[xx+tx][yy+ty].value = removeElement(c, this.elements[xx+tx][yy+ty].value);
            }
        }

        this.elements[x][y].value = c;
    }
    catch(e) {
        return false;
    }

    return true;
}

SudokuBoard.prototype.setBad = function(c, path) {
    var b = bad[path];
    if( typeof b == 'undefined' ) {
        bad[path] = c;
    }
    else {
        bad[path] += c;
    }
}

SudokuBoard.prototype.valid = function() {
    // valid if all 3x3 are ok
    var x;
    var y;
    var all;
    var r;
    for( x = 0; x < 9; x=x+3 ) {
        for( y = 0; y < 9; y=y+3 ) {
            r = this.validateBox( x, y );
            if( !r ) {
                return false;
            }
        }
    }


    // check uniqness
    for( x = 0; x < 9; x++ ) {
        r = this.validateVerticalLine(x);
        if( !r ) {
            return false;
        }

        // x-axis
        this.validateHorizontalLine(x);
        if( !r ) {
            return false;
        }
    }

    return true;
}


SudokuBoard.prototype.validateBoxAgainstElement = function( element ) {
    x = 3*Math.floor(element.x/3);
    y = 3*Math.floor(element.y/3);
    for( i = 0; i < 3; i++ ) {
        for( j = 0; j < 3; j++ ) {
            if( x+i == element.x && y+j == element.y ) {
                continue;
            }

            v = this.elements[i+x][j+y].valueSet;

            if( v == null ) {
                v = this.elements[i+x][j+y].value;
            }

            if( v != null && v == element.bid) {
                return false;
            }
        }
    }

    return true;
}


SudokuBoard.prototype.validateBox = function( x, y, notEmptyOnly ) {
    all = new Array(9);
    for( i = 0; i < 3; i++ ) {
        for( j = 0; j < 3; j++ ) {
            v = this.elements[i+x][j+y].valueSet;

            if( v == null ) {
                v = this.elements[i+x][j+y].value;
            }

            if( !notEmptyOnly && v == null )  {
                return false;
            }

            if( typeof all[v] != 'undefined' ) {
                return false;
            }
            else {
                if( v != null ) {
                    all[v] = v;
                }
            }
        }
    }

    return true;
}

SudokuBoard.prototype.validateVerticalLine = function( pp, notEmptyOnly ) {
    all = new Array(9);

    for( i = 0; i < 9; i++ ) {
        // y-axis
        v = this.elements[pp][i].valueSet;

        if( v == null ) {
            v = this.elements[pp][i].value;
        }

        if( !notEmptyOnly && v == null )  {
            return false;
        }

        if( all[v] != null ) {
            return false;
        }
        else {
            if( v != null ) {
                all[v] = v;
            }
        }
    }

    return true;



}

SudokuBoard.prototype.validateVerticalLineAgainstElement = function( element) {
    pp = element.x;
    all = new Array(9);
    for( i = 0; i < 9; i++ ) {
        if( i == element.y ) {
            continue;
        }
        v = this.elements[pp][i].valueSet;
        if( v == null ) {
            v = this.elements[pp][i].value;
        }

        if( v != null && v == element.bid) {
            return false;
        }
    }

    return true;
}

SudokuBoard.prototype.validateHorizontalLineAgainstElement = function( element) {
    pp = element.y;
    all = new Array(9);
    for( i = 0; i < 9; i++ ) {
        if( i == element.x ) {
            continue;
        }
        v = this.elements[i][pp].valueSet;
        if( v == null ) {
            v = this.elements[i][pp].value;
        }

        if( v != null && v == element.bid) {
            return false;
        }
    }

    return true;
}


SudokuBoard.prototype.validateHorizontalLine = function( pp, notEmptyOnly ) {
    all = new Array(9);
    for( i = 0; i < 9; i++ ) {
        v = this.elements[i][pp].valueSet;
        if( v == null ) {
            v = this.elements[i][pp].value;
        }
        if( !notEmptyOnly && v == null )  {
            return false;
        }

        if( typeof all[v] != 'undefined' ) {
            return false;
        }
        else {
            if( v != null ) {
                all[v] = v;
            }
        }
    }

    return true;
}


SudokuBoard.prototype.clear = function() {
    for( x = 0; x < 9; x++ ) {
        for(y = 0; y < 9; y++ ) {
            this.elements[x][y].value = null;
            this.elements[x][y].startValue = null;
            this.elements[x][y].valueSet = null;
            this.elements[x][y].bid = null;
            this.elements[x][y].possible = new Array();
            this.elements[x][y].showPossible = false;
        }
    }
}

SudokuBoard.prototype.generate = function() {

    this.clear();
    for( x = 0; x < 9; x++ ) {
        for(y = 0; y < 9; y++ ) {
            this.elements[x][y].value = all;
        }
    }

    while( path.length < 9*9 ) {
        len = path.length;
        x = Math.floor(len/9);
        y = len % 9;
        s = this.elements[x][y].value;
        c = null;
        if( s == "" ) {
            if( path.length == 0 ) {
                // FIXME throw new exception
                error('Could not generate');
            }
            c = path.charAt( path.length - 1 );
            path = path.substring( 0,  path.length - 1 );
            this.setBad( c, path );
            this.rebuildElementsFromPath( path, bad[path] );

            continue;
        }

        l = Math.floor( Math.random()*s.length );
        c =  s.charAt(l);

        this.clearElementsForElement(c, x, y);
        path +=  c;
    }

    // FIXME
    // copy to startValue

    // hide n digits;
    var n = this.numberToHide;
    for( var i = 0; i < n; i++ ) {

        x = Math.floor(Math.random()*9);
        y = Math.floor(Math.random()*9);
        if( this.elements[x][y].value != null ) {
            this.elements[x][y].value = null;
            this.elements[8-x][8-y].value = null;
        }
        else {
            if( n - i > 9*9 )  {
                break;
            }
            l = Math.floor(Math.random()*100);
            j = 0;
            do {
                j++;
                p = x+9*y +j;
                p = p % (9*9);
                e = this.elements[p%9][Math.floor(p/9)].value;

            } while ( e == null )
                this.elements[p%9][Math.floor(p/9)].value = null;
            this.elements[8-p%9][8-Math.floor(p/9)].value = null;
        }
    }
}

SudokuBoard.prototype.toString = function() {
    var x;
    var y;
    var s;
    var ss;
    for( x = 0; x < 9; x++ ) {
        s = ""
            for(y = 0; y < 9; y++ ) {
                v = this.elements[y][x].valueSet;
                if( v != null) {
                    ss += "..................."+ v;
                }
                else {
                    ss += "-----------------------";
                }
                ss = ss.substring( ss.length - 9 );
                s += ss+" | ";
            }
    }

    return s;
}

SudokuBoard.prototype.getBlockByNum = function( n ) {
    return this.blocks['b'+n];
}

SudokuBoard.prototype.getBlockByBlockId = function( id ) {

    if( !id ) {
        error('[getBlockByBlockId] Id cannot be null');
    }

    return this.blocks[id];
}


SudokuBoard.prototype.getBoardElementById = function( id ) {
    x = id.charAt(1);
    y = id.charAt(2);
    return this.elements[x-1][y-1];
}

SudokuBoard.prototype.findElement = function(xx, yy) {
    for( x = 0; x < 9; x++ ) {
        for(y = 0; y < 9; y++ ) {
            e = this.elements[x][y];
            if ( xx >= e.left && (e.left+e.w) >= xx &&  yy >= e.top  && (e.top+e.h) >= yy ) {
                return e;
            }
        }
    }
    return null;
};

SudokuBoard.prototype.setStartTime = function( d ) {
    this.startTime = d;
}

SudokuBoard.prototype.setFinishTime = function( d ) {
    this.finishTime = d;
}

SudokuBoard.prototype.getStartTime = function() {
    return this.startTime;
}

SudokuBoard.prototype.getFinishTime = function( ) {
    return  this.finishTime;
}


SudokuBoard.prototype.setLevel = function( p_level ) {
    switch(p_level) {
    case 0:
        this.numberToHide = 1;
        break;
    case 1:
        this.numberToHide = 8;
        break;
    case 2:
        this.numberToHide = 10;
        break;
    case 3:
        this.numberToHide = 12;
        break;
    case 4:
        this.numberToHide = 14;
        break;
    case 5:
        this.numberToHide = 20;
        break;


    default:
        this.numberToHide = 12;

    }

    this.level = p_level;
}

SudokuBoard.prototype.setDefaultLevel = function() {
    this.setLevel(1)
}

SudokuBoard.prototype.setBoard = function(encodedGame, format) {
    for( x = 0; x < 9; x++ ) {
        // this.elements[x] = new Array();
        for(y = 0; y < 9; y++ ) {
            c  = encodedGame.charAt(x+y*9);
            if( c == '0') {
                this.elements[x][y].value = null;
            }
            else {
                this.elements[x][y].value = parseInt(c);
            }

            this.elements[x][y].valueSet = null;
            this.elements[x][y].bid = null;
            this.elements[x][y].startValue = null;
        }
    }

    plotBoard();
}

sudoku = new SudokuBoard(9, 3);
sudoku.init();


<!--

var boardPointerVisible = false;

function onDrag(x, y) {


    var found = sudoku.findElement( x+51/2, y+51/2 );
    if(  found && found.value == null) {
        setPos( "boardPointer", 47+found.left, 18+found.top); //FIXME hard coded values
        if(!boardPointerVisible ) {
            setVisible("boardPointer", true);
            boardPointerVisible = true;
        }
    }
    else {
        setPos( "boardPointer" , 0, 0);
        if( boardPointerVisible ) {
            setVisible("boardPointer", false);
            boardPointerVisible = false;
        }
    }
}


function  onDragStart(x,y) {
    //FIXME this.style.zIndex = 232048;
}

/*
   x, y cordinates not element position (0,1...n)
 */
function onElementDrop(x, y) {
    setVisible(sudoku.boardPointer, false);

    result = sudoku.valid();

    gwtOnElementDrop("");

    if(result) {
        //showHideElement("successMenu");

        game.started = false;
    }
}


/**
    found - element of boeard array
*/
function buildPossibleHtml(found) {
    html = "";
    for( a in found.possible) {
        elr  = found.possible[a];
        if(elr != null ) {
            html += "<span>"+elr+"</span> ";
        }
    }
    return html;
}

/**
   Called when element from bord is droped.
*/
function onBordElementDrop(x, y, dropStatus) {



    var found = sudoku.findElement( x+51/2, y+51/2 );
    var swapElements = false;
    boardElement = sudoku.getBoardElementById(this.id);
    if( found && found.value == null) {
        o = getElement(found.id);

        if( sudoku.gameStatus["blockHelpersErase"] == "helpers" || dropStatus['shiftKey'] ) {
            if(!found.showPossible) {
                // swap elements
                setPos( this, boardElement.left, boardElement.top);

                boardElement.className = "klocek " + o.bid;
                o.className = "klocek " + block.styleForBlock;

                return;
            }
            else {
                if( found.possible[block.bid] != null ) {
                    found.possible[block.bid] = null;
                }
                else {
                    found.possible[block.bid] = block.bid;
                }
                found.showPossible = true;

                o.innerHTML = buildPossibleHtml(found);

                Drag.endOnObject(o);
            }

            setPos( this, boardElement.left, boardElement.top);

            return;
        }
        else {
            //found.showPossible = false;
            o.innerHTML = "";

            // set block id for this board element;
            block = sudoku.getBlockByBlockId(this.bid);

            found.bid = this.bid;
            o.bid = this.bid;
            found.valueSet = boardElement.valueSet;
            if( o != this ) {
                this.bid = null;
                boardElement.valueSet  = null;
            }


            this.className = "klocek";
            this.style.cursor = "default";
            this.style.zIndex = 0;


            o.className = "klocek " + block.styleForBlock;
            o.style.cursor = "move";
            //FIXME o.style.zIndex = 64;

            Drag.endOnObject(this);
            Drag.init(o);
            o.onDrop = onBordElementDrop;
            o.onDrag = onDrag;
            o.onDragStart  = onDragStart;

            markErrorsOnDrop(found);

            // restore possible
            if( boardElement.possible.length != 0 ) {
                this.innerHTML = buildPossibleHtml(boardElement);
            }
        }

    }
    else {
        /*
        element not found
        move it out of board
         */
    }

    setPos( this, boardElement.left, boardElement.top);
    onElementDrop(x, y);
}


/**
   Called when new element is dropped.
*/
function onBlockDrop(x, y, dropStatus) {
    var o1 = getElement("allBlockArea");
    var o2 = getElement("inner");
    var xx = (getRelPosX(o1) + x) + getRelPosX(o2) ;
    var yy = (getRelPosY(o1) + y) + getRelPosY(o2) ;

//    found = sudoku.findElement( xx+51/2, yy+51/2 );
    found = sudoku.findElement( xx, yy );

    info( "getRelPosX(o1): "+getRelPosX(o1) +" x: "+ x+ " getRelPosX(o2): "+getRelPosX(o2));
    info( xx+ " "+yy+" " + found );
    block = sudoku.getBlockByBlockId(this.bid);
    if( found && found.value == null) {
        o = getElement(found.id);
        o.className = "klocek";

        if(  sudoku.gameStatus["blockHelpersErase"] == "helpers" || dropStatus['shiftKey'] ) {
            if( found.possible[block.bid] != null ) {
                found.possible[block.bid] = null;
            }
            else {
                found.possible[block.bid] = block.bid;
            }
            found.showPossible =true;

            o.innerHTML = buildPossibleHtml(found);
        }
        else {
            found.showPossible = false;
            o.innerHTML = "";
            o.style.border="";
            // set block id for this board element;
            found.bid = this.bid;
            o.bid = this.bid;

            o.style.cursor = "move";
            o.className += " "+ block.styleForBlock;

            markErrorsOnDrop(found);


            Drag.init(o);
            o.onDrop = onBordElementDrop;
            o.onDrag = onDrag;
            o.onDragStart  = onDragStart;
            // FIXME o.style.zIndex = 64;
            found.valueSet = block.bid;
        }

        setPos( this, block.left, block.top);
    }
    else {
        setPos( this, block.left, block.top);
        // hide helping border
        oo = getElement(oldId);
        if( oo ) {
            oo.style.border="";
        }
    }

    onElementDrop(x, y);
}


var selectedBoardElement = null;

var lastOverElement = null;

function showPointerOverElement( p_element ) {
    setPos( "boardPointer", 47+p_element.left, 18+p_element.top);
    setVisible("boardPointer", true);
}

function onBordElementSelect(e) {

    e = Drag.fixE(e);

    var mouseX = e.clientX;
    var mouseY = e.clientY;

    o = getElement("inner");
    mouseX = mouseX - getPosX(o);
    mouseY = mouseY - getPosY(o);
    selectedBoardElement = sudoku.findElement( mouseX, mouseY );


    if( sudoku.gameStatus["blockHelpersErase"] == "erase" ) {
        info("TODO erase");

        if( selectedBoardElement != null  && selectedBoardElement.valueSet != null ) {
            selectedBoardElement.valueSet = null;
            setBoardElement(selectedBoardElement);
        }
   //     selectedBoardElement = null;
   //     e.cancelBubble = true;
   //     if (e.stopPropagation) e.stopPropagation();
       // return false;
    }

    if( selectedBoardElement == null  ) {
        return;
    }

    if( selectedBoardElement.value != null )  {
        selectedBoardElement = null;
    }
    else {
        mouseX = mouseX - 25;
        mouseY = mouseY - 25;

        // update sudoku object
        sudoku.boardPointerX = selectedBoardElement.x;
        sudoku.boardPointerY = selectedBoardElement.y;

        showPointerOverElement(selectedBoardElement);
    }
}


function transalteIntoArrows(p_keyCode) {
    switch(p_keyCode) {
    case 37:
        // left arrow
        return ARROW_LEFT;
    case 38:
        //up arrow
        return ARROW_UP;
    case 39:
        // right arrow
        return ARROW_RIGHT;
    case 40:
        //down arrow
        return ARROW_DOWN;
    default:
        return -1;
    }
}

var boardPointerX = 0;
var boardPointerY = 0;

function onBordElementKeyDown(e) {
    e = Drag.fixE(e);
    if( (a = transalteIntoArrows(e.keyCode) ) != -1 ) {
        r = sudoku.movePointer(a);
        if( r ) {
            selectedBoardElement = sudoku.elements[sudoku.boardPointerX][sudoku.boardPointerY];
            showPointerOverElement(selectedBoardElement);
        }
    }

    keyCode = String.fromCharCode(e.keyCode);
    if(sudoku.isBoardKey( keyCode )) {
        if( selectedBoardElement ) {
            var o = getElement( selectedBoardElement.id );
            var bid = String.fromCharCode(e.keyCode);

            // shift he used
            if( !selectedBoardElement.value ) {
                if( e.shiftKey ) {
                    addRemovePossible(selectedBoardElement, bid, o );
                }
                else {
                    o.className = "klocek " + "klocek" +String.fromCharCode(e.keyCode);
                    o.style.cursor = "move";
                    // FIXEME o.style.zIndex = 64;

                    o.bid = bid;
                    selectedBoardElement.valueSet = o.bid;
                    selectedBoardElement.bid = o.bid;
                    Drag.init(o);
                    o.onDrop = onBordElementDrop;
                    o.onDrag = onDrag;
                    o.onDragStart  = onDragStart;

                    markErrorsOnDrop(selectedBoardElement);

                }
                // turn off block marker
                setVisible(sudoku.boardPointer, false);
            }
        }

        // event handled, stop now
        return false;
    }
}


function addRemovePossible(element, bid, obj) {
    if( element.possible[bid] != null ) {
        element.possible[bid] = null;
    }
    else {
        element.possible[bid] = bid;
    }
    element.showPossible = true;

    if(element.showPossible) {
    info ( " " + buildPossibleHtml(element) );
        obj.innerHTML =  buildPossibleHtml(element);
    }
}

function hideErrorMarks() {
    setVisible("markErrorV", false);
    setVisible("markErrorB", false);
    setVisible("markErrorH", false);
}

function markErrorsOnDrop(found) {
    if( preferences.getPref("markErrorsOnDrop") ) {

        var valid = sudoku.validateHorizontalLineAgainstElement(found);
        if( !valid ) {
            setPosY("markErrorH", errorMarksH[ found.y ] );
            setVisible("markErrorH", true);
        }
        else {
            setVisible("markErrorH", false);
        }
        valid = sudoku.validateVerticalLineAgainstElement(found);
        if( !valid ) {
            setPosX("markErrorV", errorMarksV[ found.x ] );
            setVisible("markErrorV", true);
        }
        else {
            setVisible("markErrorV", false);
        }

        valid = sudoku.validateBoxAgainstElement( found );

        if( !valid ) {
            setPos("markErrorB", errorMarksH[3*Math.floor(found.x/3)], errorMarksV[3*Math.floor(found.y/3)]  );
            setVisible("markErrorB", true );
        }
        else {
            setVisible("markErrorB", false);
        }
    }
}


function init() {
    sudoku.init();
    o = getElement("inner");
    o.onmouseup = onBordElementSelect;
}


function clearOnStart(o) {
    if( o.cleared ) {
    }
    else {
        o.value = '';
        o.cleared = true;
    }
}

function sendRemark() {
    showHideRemark();
}

function enableDisableSendingRemark() {
    sendingButton = getElement('sendRemarkButton');
    remarkArea = getElement('remarkArea');
    if( remarkArea.value.length != 0 ) {
        sendingButton.disabled = false;
    }
    else {
        sendingButton.disabled = true;
    }
}

/*
    true - element shown, false otherwise
 */
function showHideElement(elementId, show) {
    o = getElement(elementId);
    oo = getElement(elementId+"Helper");
    if( error && !o ) {
        error( "No such element: "  + elementId);
    }
    if( !o ) {
        return false;
    }

    if( o.style.display == "none" || show  ) {
        if( oo ) {
            oo.style.display = "block";
        }
        o.style.display  = "block";
        return true;
    }
    else {
        o.style.display = "none";
        if( oo ) {
            oo.style.display = "none";
        }
        return false;
    }
}


function setBoardElement(e) {
            var o = getElement(e.id);
            var reset = false;

            if( e.showPossible ) {
                o.innerHTML = buildPossibleHtml(e);
            }
            else {
                // set by generator
                if( e.value != null ) {
                    o.className="klocek block"+e.value+"nailed";
                    reset = true;
                }
                else {
                    // users blocks
                    if( e.valueSet != null ) {
                        o.className="klocek klocek"+e.valueSet;
                        Drag.init(o);
                        o.onDrop = onBordElementDrop;
                        o.onDrag = onDrag;
                        o.onDragStart  = onDragStart;

                        o.style.cursor = "move";
                        //FIXME o.style.zIndex = 64;
                        o.bid = e.bid;
                    }
                    else {
                        reset = true;
                        o.className="klocek";
                    }
                }

            }


            if(reset) {
                  // reset events
                  Drag.endOnObject(o);
                  o.style.cursor = "";
            }
}

function plotBoard() {
    var e;
    var reset;

    for(x=0; x<9; x++ ) {
        for(y=0; y<9; y++ ) {
            reset = false;
            e = sudoku.elements[x][y];

            setBoardElement(e);
        }
    }
}

function hideBoard() {
    for(x=0; x<9; x++ ) {
        for(y=0; y<9; y++ ) {
            e = sudoku.elements[x][y];
            o = getElement(e.id);
            o.className="klocek";
            o.style.cursor = "";
        }
    }
}

function startNewGame() {
    // hide error marks
    hideErrorMarks();

//  sudoku.init();
//  sudoku.generate();
    //sudoku.generate(5);
    plotBoard();
    timer.start();

    game.started = true;
    //TODO hide errror marks when menu is visible

    return false;
}

function backToGame() {
    showHideMenu();
    return false;
}

function showFinishedBoard() {
    r = showHideElement("successMenu");
    return false;
}

function startNewGameAfterEnd() {
    startNewGame();
    showHideElement("successMenu");
    showHideElement("mainMenu");
    return false;
}



function getBoardState() {
    var o1 = "";
    var o2 = "";
    var o3 = "";
    var o4 = "";
    var possible = "";
    for(x=0; x<9; x++ ) {
        for(y=0; y<9; y++ ) {
            e = sudoku.elements[x][y];
            if (e.value != null) {
                o1 += e.value
            }
            else {
                o1 += ".";
            }

            if (e.valueSet != null) {
                o2 += e.valueSet;
            }
            else {
                o2 += ".";
            }

            if (e.bid != null) {
                o3 += e.bid;
            }
            else {
                o3 += ".";
            }
            o3 += "|";

            if (e.startValue != null) {
                o4 += e.startValue;
            }
            else {
                o4 += ".";
            }

            if (e.possible != null) {
                for( p in e.possible ) {
                    pp = e.possible[p];
                    if( pp != null ) {
                        possible += pp;
                    }
                }
            }
            possible += "|";

        }
    }

    return o1+"-"+o2+"-"+o3+"-"+o4+"-"+possible;
}

function setBoardState(state) {
    if(state == null ) {
        return;
    }


    try {
        i=0;
        var stateArray = state.split("-");
        var bids = null
        if( stateArray[2] != null ) {
            bids = stateArray[2].split("|");
        }
        var possible = null
        if( stateArray[4] != null ) {
            // split possible
            possible = stateArray[4].split("|");
        }

        for(x=0; x<9; x++ ) {
            for(y=0; y<9; y++ ) {
                e = sudoku.elements[x][y];
                p = x*9+y;
                c = stateArray[0].charAt(p);
                if( c != '.') {
                    e.value = c;
                }
                //valueset
                c = stateArray[1].charAt(p);
                if( c != '.') {
                    e.valueSet = c;
                }
                // bids
                c = bids[p];
                if( c != ".") {
                    e.bid = parseInt(c, 10);
                }

                c = stateArray[3].charAt(p);
                if( c != '.') {
                    e.startValue = c;
                }


                if( possible != null && possible[p] != null) {
                    allPos = possible[p];
                    e.possible = new Array();
                    for( i = 0; i< allPos.length; i++ ) {
                        pp = allPos.charAt(i);
                        e.possible[ pp ] = pp;
                        e.showPossible = true;
                    }
                }
            }
        }
    }
    catch( e ) {
        error("Could not load saved game", e);
        // contnue with empty board
        sudoku.clear();
    }

}


function initSudoku() {
   sudoku.boardPointer = getElement("boardPointer");
   document.onkeydown = onBordElementKeyDown;
}
