var hiscore = Get_Cookie('hiscore') == null ? 0 : Number(Get_Cookie('hiscore'));
var moving = false;
var currentColor = "silver";
var currentImg = "/images/blank.gif";
var selectedEl = null;
var selectedCell = new Array(2);
var index = 0;
var index2 = 0;
var indexr = 0;
var dest_el = null;
var finish_animation = 0;
var speed = 65;
var pos = null;
var svalue = 0;
var mustRemove = false;
var colorArray = ['red', 'blue', 'lime', 'yellow', 'maroon', 'aqua', 'fuchsia'];
var imagesArray = ['/images/red.gif', '/images/blue.gif', '/images/lime.gif', '/images/yellow.gif', '/images/maroon.gif', '/images/aqua.gif', '/images/fuchsia.gif'];
var Height = 9;
var Width = 9;
var shortestPath = new Array();
var nextBalls = new Array(3);
var nextBallsImg = new Array(3);
var maxPathLength = (Width + Height) * 2;
var cellHTable = {};
var removing = new Array();
var balls_to_remove = new Array();
var matrix = new Array(Height);
var gameEnded = false;
var aTimer = null;
var rTimer = null;
var r_remove_balls=0;

function moveDomObj(id, l, t) {
    var domObj = document.getElementById(id);
    domObj.style.left = l + "px";
    domObj.style.top = t + "px";
} /* init matrix and cellHTable */
for (var x = 0; x < matrix.length; x++) {
    matrix[x] = new Array(Width);
    for (var y = 0; y < matrix[x].length; y++) {
        matrix[x][y] = 0;
        var tdId = MakeID(x, y);
        cellHTable[tdId] = 0;
    }
}

function setMatrixAndCheckCells() {
    var emptyCells = 0;
    for (var x = 0; x < Height; x++) {
        for (var y = 0; y < Width; y++) {
            var tdId = MakeID(x, y);
            matrix[x][y] = cellHTable[tdId];
            if (matrix[x][y] != -1)++emptyCells;
        }
    }
    return emptyCells;
}

function matrixValue(mtx) {
    var r = "";
    for (var x = 0; x < Height; x++) {
        for (var y = 0; y < Width; y++)
        r += mtx[x][y];
        r += "\n";
    }
    return r;
}

function SetPosValue(x, y, val) {
    matrix[x][y] = val;
}

function SetStartPos(x, y) {
    SetPosValue(x, y, -2);
}

function SetEndPos(x, y) {
    SetPosValue(x, y, 1);
}

function FindPath(startcell, endcell) {
    SetStartPos(startcell.x, startcell.y);
    SetEndPos(endcell.x, endcell.y);
    var found = false;
    var current = 1;
    while ((current < (maxPathLength + 1)) && (!found)) {
        for (var i = 0; i < Height; i++) {
            for (var j = 0; j < Width; j++) {
                if (matrix[i][j] == current) {
                    if (CheckNeighbour(i - 1, j, current + 1)) {
                        found = true;
                    }
                    if (CheckNeighbour(i + 1, j, current + 1)) {
                        found = true;
                    }
                    if (CheckNeighbour(i, j - 1, current + 1)) {
                        found = true;
                    }
                    if (CheckNeighbour(i, j + 1, current + 1)) {
                        found = true;
                    }
                }
            }
        }
        current++;
    }
    if (found) {
        if (shortestPath)
          delete shortestPath;
        shortestPath = new Array(current - 1);
        pos = startcell;
        index = 0;
        initTheBall(pos.x, pos.y);
        resetCell(pos.x, pos.y, 0);
        while ((pos.x != endcell.x) || (pos.y != endcell.y)) { /**/
            if (shortestPath[index])
              delete shortestPath[index];
            shortestPath[index] = new Array(2);
            pos = GetMinNearest(pos);
            shortestPath[index].x = pos.x;
            shortestPath[index].y = pos.y;
            ++index;
        }
        startAnimation();
        return true;
    } else {
        shortestPath = null;
        return false;
    }
}

function startAnimation() {
    aTimer = window.setInterval(stepBall, speed);
}

function stepBall() {
    x = shortestPath[index2].x;
    y = shortestPath[index2].y;
    var cell = document.getElementById(MakeID(x, y));
    var ol = cell.offsetLeft + 5;
    var ot = cell.offsetTop + 2;
    moveDomObj("ball", ol, ot);
    index2++;
    if (index2 == index) {
        clearInterval(aTimer);
        index2 = 0;
        finish_animation = 1;
        removeTheBall();
        var img_dest = dest_el.childNodes[0];
        img_dest.style.visibility = "visible";
    }
}

function initTheBall(x, y) {
    var theBall = document.getElementById("ball");
    var theCell = document.getElementById(MakeID(x, y));
    theBall.style.display = "";
    theBall.src = currentImg;
    var l = theCell.offsetLeft + 5;
    var t = theCell.offsetTop + 2;
    theBall.style.left = l + "px";
    theBall.style.top = t + "px";
}

function removeTheBall() {
    var theBall = document.getElementById("ball");
    theBall.style.display = "none";
}

function resetCell(x, y, col) {
    var theCell = document.getElementById(MakeID(x, y));
    if (col == 0) {
        theCell.style.color = 'silver';
        theCell.childNodes[0].src = '/images/blank.gif';
    } else {
        theCell.style.color = currentColor;
        theCell.childNodes[0].src = currentImg;
    }
}

function CheckNeighbour(x, y, val) {
    if (IsInBounds(x, y)) {
        if (matrix[x][y] == -2) {
            return true;
        }
        if (matrix[x][y] == 0) {
            matrix[x][y] = val;
        }
    }
    return false;
}

function IsInBounds(x, y) {
    if ((x < 0) || (y < 0) || (y >= Width) || (x >= Height)) {
        return false;
    }
    return true;
}

function GetMinNearest(pos) {
    var min = matrix[pos.x][pos.y];
    var result = pos;
    var x, y;
    x = pos.x - 1;
    y = pos.y;
    delete result;
    if (IsInBounds(x, y) && (matrix[x][y] > 0)) {
        if ((min < 0) || (matrix[x][y] < min)) {
            min = matrix[x][y];
            result = new Array(2);
            result['x'] = x;
            result['y'] = y;
        }
    }
    x = pos.x + 1;
    y = pos.y;
    if (IsInBounds(x, y) && (matrix[x][y] > 0)) {
        if ((min < 0) || (matrix[x][y] < min)) {
            min = matrix[x][y];
            result = new Array(2);
            result['x'] = x;
            result['y'] = y;
        }
    }
    x = pos.x;
    y = pos.y - 1;
    if (IsInBounds(x, y) && (matrix[x][y] > 0)) {
        if ((min < 0) || (matrix[x][y] < min)) {
            min = matrix[x][y];
            result = new Array(2);
            result['x'] = x;
            result['y'] = y;
        }
    }
    x = pos.x;
    y = pos.y + 1;
    if (IsInBounds(x, y) && (matrix[x][y] > 0)) {
        if ((min < 0) || (matrix[x][y] < min)) {
            min = matrix[x][y];
            result = new Array(2);
            result['x'] = x;
            result['y'] = y;
        }
    }
    return result;
}

function Move(el) {
    var currentCell = getXY(el.id);
    if (!moving && cellHTable[el.id] == -1) {
        selectedEl = el;
        selectedCell = getXY(selectedEl.id);
        currentColor = el.style.color;
        currentImg = el.childNodes[0].src;
        el.style.border = "1px inset white";
        el.style.backgroundColor = "gray";
        moving = true;
    } else if (moving) {
        if (cellHTable[el.id] == -1) {
            selectedEl.style.backgroundColor = "silver";
            selectedEl.style.border = "1px outset silver";
            selectedEl = el;
            selectedCell = getXY(selectedEl.id);
            currentColor = el.style.color;
            currentImg = el.childNodes[0].src;
            el.style.border = "1px inset white";
            el.style.backgroundColor = "gray";
        } else {
            if (!FindPath(selectedCell, currentCell)) return;
            else {
                selectedEl.style.border = "1px outset silver";
                selectedEl.style.color = "silver";
                selectedEl.childNodes[0].src = "/images/blank.gif";
                selectedEl.style.backgroundColor = "silver";
                cellHTable[selectedEl.id] = 0;
            }
            el.childNodes[0].style.visibility = "hidden";
            el.style.color = currentColor;
            el.childNodes[0].src = currentImg;
            cellHTable[el.id] = -1;
            dest_el = el;
            moving = false;
            var emptycells;
            indexr=index;
            if (CheckTable(false)) {
                //alert(indexr);
                emptycells = setMatrixAndCheckCells();
                setTimeout(function () {
                    Deal(emptycells)
                }, 2*(indexr) * speed);
            }
            indexr=index;
            rTimer = window.setInterval(Removeballs, (indexr+1)*speed);
            
            
//            CheckTable(true);
//            indexr=index;
//            rTimer = window.setInterval(Removeballs, 8*(indexr)*speed);
            
            
            if (emptycells <= 3) {
                gameEnded = true;
                alert("Gioco finito col punteggio di " + document.forms['scores'].scval.value);
                var finalscore = Number(document.forms['scores'].scval.value);
                if (finalscore > hiscore) Set_Cookie('hiscore', finalscore, 1000);
                document.forms['scores'].submit();
            } else setMatrixAndCheckCells();
            
        }
    }
}

function MakeID(row, column) {
    return "cell" + row + "_" + column;
}

function getXY(id) {
    var rc = new Array(2);
    rc['x'] = Number(id.charAt(4));
    rc['y'] = Number(id.charAt(6));
    return rc;
}

function CheckTable(afterdeal) {
    for (var i = 0; i < Height; i++)
    for (var j = 0; j < Width; j++) {
        CheckDirections(i, j);
    }
    var svalue = Number(document.forms['scores'].scval.value);
/* Punteggio:
   2 punti per palla per 5 palle
   6� palla -> 4 punti (2^2)
   7� palla -> 8 punti (2^3)
   8� palla -> 16 punti (2^4)
   9� palla -> 32 punti (2^5  )
  */
    for (var r = 0; r < removing.length; r++) {
       var scorefactor = (r < 5) ? 2 : (Math.pow(2, (r - 3)));
       cellHTable[removing[r]] = 0;
       svalue += scorefactor;
    }
    setMatrixAndCheckCells();
    balls_to_remove = removing;
    if (!afterdeal) document.forms['scores'].scval.value = svalue;
    if (removing.length > 0) {
        delete removing;
        removing = new Array();
        return false;
    } else return true;
}

function Removeballs() {
    if (document.getElementById(balls_to_remove[r_remove_balls])) {
        document.getElementById(balls_to_remove[r_remove_balls]).style.color = "silver";
        document.getElementById(balls_to_remove[r_remove_balls]).childNodes[0].src = "/images/blank.gif";
        document.getElementById("ball").src = "/images/blank.gif";
        //cellHTable[balls_to_remove[r_remove_balls]] = 0;
        indexr = -0.75;
        r_remove_balls++;
        if (r_remove_balls == balls_to_remove.length) {
            clearInterval(rTimer);
            r_remove_balls = 0;
            delete balls_to_remove;
            balls_to_remove = new Array();
            mustRemove = false;
            CheckTable(true);
            indexr=index;
            rTimer = window.setInterval(Removeballs, (indexr+1)*speed);
        }
    } else clearInterval(rTimer);
}

function CheckDirections(i, j) {
    if (i <= 4) {
        CheckDirection(i, j, 2);
        if (j >= 4) {
            CheckDirection(i, j, 3);
        }
    }
    if (j <= 4) {
        CheckDirection(i, j, 0);
        if (i <= 4) {
            CheckDirection(i, j, 1);
        }
    }
}

function iof(array, val) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] == val) return i;
    }
    return -1;
}

function CheckDirection(i, j, dir) {
    var id = MakeID(i, j);
    if (cellHTable[id] != -1) return;
    var ijcol = document.getElementById(id).style.color;
    var ccol;
    var rcandidate = new Array();
    rcandidate.push(id);
    var r = "";
    do {
        switch (dir) {
        case 0:
            id = MakeID(i, ++j);
            break;
        case 1:
            id = MakeID(++i, ++j);
            break;
        case 2:
            id = MakeID(++i, j);
            break;
        case 3:
            id = MakeID(++i, --j);
            break;
        }
        if (!IsInBounds(i, j)) break;
        ccol = document.getElementById(id).style.color;
        if (ccol == ijcol) {
            rcandidate.push(id);
        } else break;
    } while (iof(removing, id) == -1)
    if (rcandidate.length > 4) removing = removing.concat(rcandidate);
    delete rcandidate;
}

function preDealBalls() {
    for (var i = 0; i < 3; i++) {
        var rndIdx = Math.floor(Math.random() * 7);
        var rndCol = colorArray[rndIdx];
        nextBalls[i] = rndCol;
        var id = "ball" + i;
        var el = document.getElementById(id);
        el.style.color = rndCol;
        el.childNodes[0].src = imagesArray[rndIdx];
        nextBallsImg[i] = imagesArray[rndIdx];
    }
}

function Deal(emptycells) {
    var deals = 3
    if (emptycells < 3) deals = emptycells;
    for (var i = 0; i < deals; i++) {
        var id = "";
        do {
            var randomnumber = Math.floor(Math.random() * Height * Width);
            var row = Math.floor(randomnumber / Height);
            var column = randomnumber % Width;
            id = MakeID(row, column);
        } while (cellHTable[id] == -1);
        var theTd = document.getElementById(id);
        theTd.style.color = nextBalls[i];
        theTd.childNodes[0].src = nextBallsImg[i];
        cellHTable[id] = -1;
        matrix[row][column] = -1;
    }
    preDealBalls();
}

function initGame() {
    preDealBalls();
    Deal(81);
    document.forms['scores'].hscval.value = hiscore;
}

function showOrHideNext() {
    var el = document.getElementById("nextballs");
    if(el)
      el.style.display = (el.style.display == '') ? "none" : "";
}
