var isMoving = false,
    diskOrigin, diskDestiny, movements;
var nWrongMoves = 0;
var moves = [],
    totalMoves = []; //vector to save movements
var acertou = 0;
var optimalSolution;
var redo = false,
    undo = false;
var textDict = {
    disk0: "stroked0",
    disk1: "stroked1",
    disk2: "stroked2",
    disk3: "stroked3",
    disk4: "stroked4",
    disk5: "stroked5",
    stroked0: "disk0",
    stroked1: "disk1",
    stroked2: "disk2",
    stroked3: "disk3",
    stroked4: "disk4",
    stroked5: "disk5"
};

var wrongBuzz = new Audio('assets/sounds/wrongBuzz.mp3');
//freesounds.org

//To know which tower was selected
function getTower(id) {
    switch (id) {
        case 0:
            return towerA;
        case 1:
            return towerB;
        case 2:
            return towerC;
    }
}

function selectA() {
    if (!isMoving) {
        if (towerA.length > 0) {
            diskOrigin = 0;
            isMoving = true;
            towerA[towerA.length - 1].setTexture(textDict[towerA[towerA.length - 1].texture.key]);
        }
    } else {
        if (diskOrigin != 0) {
            moveFromTo(diskOrigin, 0);
        } else {
            towerA[towerA.length - 1].setTexture(textDict[towerA[towerA.length - 1].texture.key]);
            isMoving = false;
            nMoves.text++;
        }
    }
}

function selectB() {
    if (!isMoving) {
        if (towerB.length > 0) {
            diskOrigin = 1;
            isMoving = true;
            towerB[towerB.length - 1].setTexture(textDict[towerB[towerB.length - 1].texture.key]);
        }
    } else {
        if (diskOrigin != 1) {
            moveFromTo(diskOrigin, 1);
        } else {
            towerB[towerB.length - 1].setTexture(textDict[towerB[towerB.length - 1].texture.key]);
            isMoving = false;
            nMoves.text++;
        }
    }
}

function selectC() {
    if (!isMoving) {
        if (towerC.length > 0) {
            diskOrigin = 2;
            isMoving = true;
            towerC[towerC.length - 1].setTexture(textDict[towerC[towerC.length - 1].texture.key]); //levantar o disco
        }
    } else {
        if (diskOrigin != 2) {
            moveFromTo(diskOrigin, 2);
        } else {
            towerC[towerC.length - 1].setTexture(textDict[towerC[towerC.length - 1].texture.key]);
            isMoving = false;
            nMoves.text++;
        }
    }
}


function moveFromTo(origin, destiny) {
    var originTower = getTower(origin),
        destinyTower = getTower(destiny);
    var topDiskOrigin = originTower[originTower.length - 1],
        topDiskDestiny;
    if (!undo && !redo) {
        topDiskOrigin.setTexture(textDict[topDiskOrigin.texture.key]);
    }
    if (destinyTower.length > 0) {
        //movement to a tower with a disk in it
        topDiskDestiny = destinyTower[destinyTower.length - 1];
        if (topDiskOrigin.displayWidth <= topDiskDestiny.displayWidth) {
            topDiskOrigin.x += 435 * (destiny - origin);
            topDiskOrigin.y += 28 * (originTower.length - destinyTower.length - 1);
            originTower.pop();
            destinyTower.push(topDiskOrigin);
            //control variables
            nMoves.text++;
            totalMoves.push(origin + "  " + destiny);
            if (!undo) {
                //if it is either a redo or a new move we must add new moves to the current sequence for possible 'undos'
                if (!redo) {
                    //if it is a new move, we clean all possible "redos"
                    moves.splice(nCurrentMoves, moves.length - nCurrentMoves);
                    moves.push(origin + "  " + destiny);
                }
                nCurrentMoves++;
                undoButton.setInteractive({ useHandCursor: true });
                undoButton.setTexture('undo');
                if (nCurrentMoves == moves.length) {
                    redoButton.disableInteractive();
                    redoButton.setTexture('redoDisabled');
                }
                redo = false;
            } else {
                nCurrentMoves--;
                undo = false;
                redoButton.setInteractive({ useHandCursor: true });
                redoButton.setTexture('redo');
                if (nCurrentMoves == 0) {
                    undoButton.disableInteractive();
                    undoButton.setTexture('undoDisabled');
                }
            }
        } else {
            invalidMovement(destiny);
        }
    } else {
        //move to a tower without a disk in it
        topDiskOrigin.x += 435 * (destiny - origin);
        topDiskOrigin.y += 28 * (originTower.length - destinyTower.length - 1);
        originTower.pop();
        destinyTower.push(topDiskOrigin);
        //control variables
        nMoves.text++;
        totalMoves.push(origin + "  " + destiny);
        if (!undo) {
            //if it is either a redo or a new move we must add new moves to the current sequence for possible 'undos'
            if (!redo) {
                //if it is a new move, we clean all possible "redos" and add the new move to the list
                moves.splice(nCurrentMoves, moves.length - nCurrentMoves);
                moves.push(origin + "  " + destiny);
            }
            nCurrentMoves++;
            if (nCurrentMoves == moves.length) {
                redoButton.disableInteractive();
                redoButton.setTexture('redoDisabled');
            }
            undoButton.setInteractive({ useHandCursor: true });
            undoButton.setTexture('undo');
            redo = false;
        } else {
            nCurrentMoves--;
            undo = false;
            redoButton.setInteractive({ useHandCursor: true });
            redoButton.setTexture('redo');
            if (nCurrentMoves == 0) {
                undoButton.disableInteractive();
                undoButton.setTexture('undoDisabled');
            }
        }
    }
    movements += origin + " " + destiny + "\n"
    isMoving = false;
    if (towerC.length == diskQntity) {
        if (nMoves.text == minimumMoves) {
        	outputMsgBox.alpha = 0.8;        
        	gameWonMsg.text = "Parabéns!\n\nVocê moveu a torre em " + nMoves.text + " movimentos!\nMÍNIMO DE MOVIMENTOS POSSÍVEIS!";
        } else {
        	outputMsgBox.alpha = 0.8;
		    gameWonMsg.text = "Parabéns!\n\nVocê moveu a torre em " + nMoves.text + " movimentos!\n(Mínimo de movimentos possíveis: " + minimumMoves + ")";
        }
    } else {
        outputMsgBox.alpha = 0;
        gameWonMsg.text = ' ';
    }
}

function redoMove() {
    if (nCurrentMoves < moves.length) {
        var res = moves[nCurrentMoves].split("  ");
        redo = true;
        moveFromTo(parseInt(res[0]), parseInt(res[1]));
        if (nCurrentMoves == moves.length) redoButton.setInteractive({ useHandCursor: false });
    }
}

function undoMove() {
    if (nCurrentMoves > 0) {
        var res = moves[nCurrentMoves - 1].split("  ");
        undo = true;
        moveFromTo(parseInt(res[1]), parseInt(res[0]));
        if (nCurrentMoves == 0) undoButton.setInteractive({ useHandCursor: false });
        redoButton.setInteractive({ useHandCursor: true });
    }
}

function destroyDisks(torre) {
    for (var i = 0; i < torre.length; i++) {
        torre[i].destroy();
    }
    torre.splice(0, torre.length);
}

function restart(n = 0) {
    if (n > 0) diskQntity = n;
    restartVariables();
    var diskX = 220,
        diskY = 430;
    for (var i = diskQntity - 1; i >= 0; i--) {
        towerA[diskQntity - 1 - i] = scene.add.sprite(diskX, diskY, 'disk' + i).setScale(0.13); //.setDisplaySize(diskWidth, diskHeight);
        diskY -= 28;
    }

    outputMsgBox.alpha = 0;
    gameWonMsg.text = ' ';

}

function restartVariables() {
    destroyDisks(towerA);
    destroyDisks(towerB);
    destroyDisks(towerC);
    isMoving = false;
    moves.splice(0, moves.length);
    nCurrentMoves = 0;
    minimumMoves = Math.pow(2, diskQntity) - 1;
}

function selectDisks(qntity, game) {
    diskQntity = qntity;
    restartVariables();
    game.scene.start('sceneGame');

}


function invalidMovement(torre) {
    wrongMoveSprite.setX(220 + torre * 435);
    wrongBuzz.play();
    wrongMoveSprite.setAlpha(1);
    scene.time.delayedCall(1000, hideX, [], scene);
}

function hideX() {
    wrongMoveSprite.setAlpha(0);
}