import { ActionFormData } from "@minecraft/server-ui";
import { system } from "@minecraft/server";
import * as utils from "../utils";
import * as gld from "../gld";
import * as inventory_utils from "../inventory_utils";
import { showApp as main_menu, checkDepletedBattery } from "./main_menu"; 
import { stopMusic } from "./play_music";

const quizGld = {"Easy" : { name: "easy", operands: "++-+-", addOp1: [ 3, 13 ], addOp2: [ 15, 25 ], multOp1: [ 1, 1 ], multOp2: [ 1, 1 ]  },
                "Medium" : { name: "medium", operands: "+-+**--+*-", addOp1: [ 7, 17 ], addOp2: [ 17, 35 ], multOp1: [ 3, 7 ], multOp2: [ 7, 15 ] },
                "Hard" : { name: "hard", operands: "+-+*/-+/-*+*/-+", addOp1: [ 12, 19 ], addOp2: [ 25, 45 ], multOp1: [ 7, 13 ], multOp2: [ 9, 19 ] },
};

let tickStart = 0;
let tickEnd = 0;
export async function showApp(player){
    if (await checkDepletedBattery(player))
        return;

    let easyStat = await utils.loadEntityParam(player, "goe_spa_easy_quiz_result", 0);
    let mediumStat = await utils.loadEntityParam(player, "goe_spa_medium_quiz_result", 0);
    let hardStat = await utils.loadEntityParam(player, "goe_spa_hard_quiz_result", 0);

    let mathWizQuizData = gld.getAppData("math_wiz_quiz");
    let quizFrontPageText = "Welcome to Math Wiz Quiz (Mini game)\n\n"
                            + "You will get a series of random mathematical equations, and your goal is to answer as many questions as possible correctly.\n"
                            + "Let's see if you can solve them all.\n\n"
                            + "Stats:\n"
                            + `§aEasy§f: ${easyStat}/5 correct answers\n`
                            + `§6Medium§f: ${mediumStat}/10 correct answers\n`
                            + `§cHard§f: ${hardStat}/15 correct answers\n\n`;

    
    let mathWizQuizForm = new ActionFormData().title(mathWizQuizData.name);
    mathWizQuizForm.body(gld.getScreenTitle(player) + quizFrontPageText);
    mathWizQuizForm.button("§0Reset Stats", "textures/goe/spa/ui/delete");
    mathWizQuizForm.button("§aPlay Easy", "textures/goe/spa/ui/quiz_easy");
    mathWizQuizForm.button("§6Play Medium", "textures/goe/spa/ui/quiz_medium");
    mathWizQuizForm.button("§cPlay Hard", "textures/goe/spa/ui/quiz_hard");
    mathWizQuizForm.button("§0Back", "textures/goe/spa/ui/back");
    
    mathWizQuizForm.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        let playerPressed = response.selection;
        player.playSound("goe_spa:button_click");
        utils.runPlayerCommand(player, "stopsound @s goe_spa:mini_game_music");

        switch(playerPressed) {
            case 0:
                // Reset stats
                showConfirmForm(player, mathWizQuizData).then(result => {
                    inventory_utils.replacePhoneIfUIClosed(player, result);
                    if (result.canceled)
                        return;
    
                    if (result.selection === 0) {
                        player.playSound("goe_spa:delete");
                        resetStats(player);
                    } else {
                        player.playSound("goe_spa:cancel");
                    }
                    
                    showApp(player);
                }).catch(error => {
                    //utils.debug(error.message);
                });
                break;
            case 1:
                stopMusic(player, false);
                player.playSound("goe_spa:button_click");
                player.playSound("goe_spa:mini_game_music");
                showQuizStepForm(player, mathWizQuizData, quizGld.Easy, 0, 0, undefined);
                break;
            case 2:
                stopMusic(player, false);
                player.playSound("goe_spa:button_click");
                player.playSound("goe_spa:mini_game_music");
                showQuizStepForm(player, mathWizQuizData, quizGld.Medium, 0, 0, undefined);
                break;
            case 3:
                stopMusic(player, false);
                player.playSound("goe_spa:button_click");
                player.playSound("goe_spa:mini_game_music");
                showQuizStepForm(player, mathWizQuizData, quizGld.Hard, 0, 0, undefined);
                break;
            case 4:
                player.playSound("goe_spa:button_click");
                main_menu(player);
                break;
        }
    });
}



async function showQuizStepForm(player, mathWizQuizData, quizData, step, correctAnswers, previousCorrectAnswer) {

    if (step === 0)
        tickStart = system.currentTick;
    let equation = prepareEquation(quizData, step);
    let previousAnswerText = "";
    if (previousCorrectAnswer === true)
        previousAnswerText = "§aCorrect answer!§r\n\n";
    else if (previousCorrectAnswer === false)
        previousAnswerText = "§cWrong answer!§r\n\n";
    const QuizStepForm = new ActionFormData()
        .title(mathWizQuizData.name)
        .body(`${gld.getScreenTitle(player)}\n${previousAnswerText}§lStep ${step+1}/${quizData.operands.length}: Solve the equation:\n\n${equation.text}§r\n\n`)
        .button(`§l${equation.answers[0]}`, "textures/goe/spa/ui/answer1")
        .button(`§l${equation.answers[1]}`, "textures/goe/spa/ui/answer2")
        .button(`§l${equation.answers[2]}`, "textures/goe/spa/ui/answer3")
        .button("§l§cBack", "textures/goe/spa/ui/cancel");

        QuizStepForm.show(player).then((response) => {
            inventory_utils.replacePhoneIfUIClosed(player, response);
            if (response.canceled) {
                utils.runPlayerCommand(player, "stopsound @s goe_spa:mini_game_music");
                return;
            }

        let playerPressed = response.selection;
        if (playerPressed <= 2)
        {
            let isCorrectAnswer = playerPressed === equation.correctAnswer;
            correctAnswers += isCorrectAnswer ? 1 : 0;
            let nextStep = step+1;

            if (isCorrectAnswer) player.playSound("goe_spa:correct_answer");
            else player.playSound("goe_spa:wrong_answer");

            if (nextStep < quizData.operands.length)
                showQuizStepForm(player, mathWizQuizData, quizData, step+1, correctAnswers, isCorrectAnswer);
            else 
                showQuizLastStepForm(player, mathWizQuizData, quizData, correctAnswers, isCorrectAnswer);
            //else if (correctAnswers === quizData.operands.length)
            //    showQuizWinForm(player, mathWizQuizData, quizData, correctAnswers);
            //else
            //    showQuizLoseForm(player, mathWizQuizData, quizData, correctAnswers, isCorrectAnswer);
        }
        else {
            utils.runPlayerCommand(player, "stopsound @s goe_spa:mini_game_music");
            player.playSound("goe_spa:button_click");
            main_menu(player);
        }

    });
}

function updateQuizStat(player, statName, prevValue, newValue)
{
    if (prevValue < newValue)
    {
        player.setDynamicProperty(statName, newValue);
        return newValue;
    }
    return prevValue;
}
async function showQuizWinForm(player, mathWizQuizData, quizData, correctAnswers) {
    // Stop music
    utils.runPlayerCommand(player, "stopsound @s goe_spa:mini_game_music");

    tickEnd = system.currentTick;
    let quizTime = tickEnd - tickStart;
    quizTime = Math.floor(quizTime / 20) ; // seconds;
    let seconds = `${quizTime % 60}`.padStart(2, "0");
    let minutes = Math.floor(quizTime / 60);
    let previousBestTime = player.getDynamicProperty("goe_spa_best_quiz_time");
    let highscoreText = "";
    if (previousBestTime === undefined || previousBestTime > quizTime)
    {
        player.setDynamicProperty("goe_spa_best_quiz_time", quizTime);
        highscoreText == `Well done! You made a new record!\n\n`;
    }
    let easyStat = await utils.loadEntityParam(player, "goe_spa_easy_quiz_result", 0);
    let mediumStat = await utils.loadEntityParam(player, "goe_spa_medium_quiz_result", 0);
    let hardStat = await utils.loadEntityParam(player, "goe_spa_hard_quiz_result", 0);
    if (quizData.name === "easy")
        easyStat = updateQuizStat(player, "goe_spa_easy_quiz_result", easyStat, correctAnswers);
    else if (quizData.name === "medium")
        mediumStat = updateQuizStat(player, "goe_spa_medium_quiz_result", mediumStat, correctAnswers);
    else
        hardStat = updateQuizStat(player, "goe_spa_hard_quiz_result", hardStat, correctAnswers);

    // Firework particles
    player.playSound("goe_spa:win");
    player.playSound("goe_spa:victory");
    playerFireworks(player, {x: 1.5, y: 0.5, z: 2});
    system.runTimeout(() => playerFireworks(player, {x: -1.5, y: 0, z: 2}), 5);
    system.runTimeout(() => playerFireworks(player, {x: 1.5, y: 0, z: 2}), 10);
    system.runTimeout(() => playerFireworks(player, {x: -1.5, y: 0.5, z: 2}), 15);

    const QuizWinForm = new ActionFormData()
        .title(mathWizQuizData.name)
        .body(`${gld.getScreenTitle(player)}\n\n§eCongratulations, you did it!§f\n\n`
                    +`You beat the ${quizData.name} contest in ${minutes}:${seconds} minutes!\n\n${highscoreText}`
                    + "Stats:\n"
                    + `§aEasy§f: ${easyStat}/5 correct answers\n`
                    + `§6Medium§f: ${mediumStat}/10 correct answers\n`
                    + `§cHard§f: ${hardStat}/15 correct answers\n\n`)
        .button("Try Again", "textures/goe/spa/ui/math_wiz_quiz")
        .button("Back", "textures/goe/spa/ui/back");

     QuizWinForm.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        player.playSound("goe_spa:button_click");
        let playerPressed = response.selection;
        if (playerPressed === 0)
            showApp(player);
        else
            main_menu(player);
    });
}
async function showQuizLastStepForm(player, mathWizQuizData, quizData, correctAnswers, previousCorrectAnswer) {
    // Stop music
    utils.runPlayerCommand(player, "stopsound @s goe_spa:mini_game_music");
    
    let previousAnswerText = "";
    if (previousCorrectAnswer === true)
        previousAnswerText = "§aCorrect answer!\n\n";
    else if (previousCorrectAnswer === false)
        previousAnswerText = "§cWrong answer!\n\n";

    const QuizLastStepForm = new ActionFormData()
        .title(mathWizQuizData.name)
        .body(`${gld.getScreenTitle(player)}\n${previousAnswerText}§r\n\n`)
        .button("Finish Quiz", "textures/goe/spa/ui/math_wiz_quiz");

        QuizLastStepForm.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        player.playSound("goe_spa:button_click");
        if (correctAnswers === quizData.operands.length)
            showQuizWinForm(player, mathWizQuizData, quizData, correctAnswers);
        else
            showQuizLoseForm(player, mathWizQuizData, quizData, correctAnswers, previousCorrectAnswer);
        
    });
}


async function showQuizLoseForm(player, mathWizQuizData, quizData, correctAnswers, previousCorrectAnswer) {
    // Stop music
    utils.runPlayerCommand(player, "stopsound @s goe_spa:mini_game_music");
    
    let previousAnswerText = "";
    //if (previousCorrectAnswer === true)
     //   previousAnswerText = "§aCorrect answer!\n\n";
    //else if (previousCorrectAnswer === false)
    //    previousAnswerText = "§cWrong answer!\n\n";

    let easyStat = await utils.loadEntityParam(player, "goe_spa_easy_quiz_result", 0);
    let mediumStat = await utils.loadEntityParam(player, "goe_spa_medium_quiz_result", 0);
    let hardStat = await utils.loadEntityParam(player, "goe_spa_hard_quiz_result", 0);
    if (quizData.name === "easy")
        easyStat = updateQuizStat(player, "goe_spa_easy_quiz_result", easyStat, correctAnswers);
    else if (quizData.name === "medium")
        mediumStat = updateQuizStat(player, "goe_spa_medium_quiz_result", mediumStat, correctAnswers);
    else
        hardStat = updateQuizStat(player, "goe_spa_hard_quiz_result", hardStat, correctAnswers);

    player.playSound("goe_spa:lose");

    const QuizWinForm = new ActionFormData()
        .title(mathWizQuizData.name)
        .body(`${gld.getScreenTitle(player)}\n${previousAnswerText}§rNice going. You finished the ${quizData.name} contest!\n`
                    +`Correct answers: ${correctAnswers}/${quizData.operands.length}.\n\n`
                    +`No new record achived; you'll get it next time.\n\n`
                    + "Stats:\n"
                    + `§aEasy§f: ${easyStat}/5 correct answers\n`
                    + `§6Medium§f: ${mediumStat}/10 correct answers\n`
                    + `§cHard§f: ${hardStat}/15 correct answers\n\n`)
        .button("Try Again", "textures/goe/spa/ui/math_wiz_quiz")
        .button("Back", "textures/goe/spa/ui/back");

     QuizWinForm.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        player.playSound("goe_spa:button_click");
        let playerPressed = response.selection;
        if (playerPressed === 0)
            showApp(player);
        else
            main_menu(player);
    });
}


function prepareEquation(quizData, step)
{
    let operand = quizData.operands[step];
    let op1 = (operand === "+" || operand === "-") ? getRandomNumber(quizData.addOp1) : getRandomNumber(quizData.multOp1);
    let op2 = (operand === "+" || operand === "-") ? getRandomNumber(quizData.addOp2) : getRandomNumber(quizData.multOp2);
    let answer = (operand === "+" || operand === "-") ? op1 + op2 : op1 * op2;

    if (operand === "-" || operand === "/")
    {
        let tmp = op1;
        op1 = answer;
        answer = tmp;
    }
    let equation = { text: `${op1} ${operand} ${op2} = ?`, answers: [], correctAnswer: 0};
    let correctAnswer = ` ${answer} `;
    let answers = [ correctAnswer, ` ${answer+distractor(true)} `, ` ${answer+distractor(false)} `];
    equation.answers = shuffle(answers);
    if (equation.answers[0] === correctAnswer)
        equation.correctAnswer = 0;
    else if (equation.answers[1] === correctAnswer)
        equation.correctAnswer = 1;
    else 
        equation.correctAnswer = 2;


    return equation;
}
function getRandomNumber(numRange)
{
    return Math.floor(Math.random() * (numRange[1]-numRange[0]+1))+numRange[0];
}
function distractor(isSmallDistractor)
{
    let smallDistractor = [ 2, 4, -2, -4];
    let bigDistractor = [ 6, 8, 10, -6, -8, -10 ];
    let selectedOption = isSmallDistractor ? Math.floor(Math.random()*4) : Math.floor(Math.random()*6);
    return isSmallDistractor ? smallDistractor[selectedOption] : bigDistractor[selectedOption];
}
function shuffle(array) {
    let currentIndex = array.length;
  
    // While there remain elements to shuffle...
    while (currentIndex != 0) {
  
      // Pick a remaining element...
      let randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex--;
  
      // And swap it with the current element.
      [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
    }
    return array;
}

async function showConfirmForm(player, mathWizQuizData) {
    // Set layout
    const ConfirmForm = new ActionFormData();
    ConfirmForm.title(mathWizQuizData.name);
    ConfirmForm.body(
        `All game stats will be deleted and set back to zero.\n\n` + 
        `Are you sure?`
    );

    ConfirmForm.button("§aConfirm", "textures/goe/spa/ui/confirm");
    ConfirmForm.button("§4Cancel", "textures/goe/spa/ui/cancel");

    // Return promise
    return ConfirmForm.show(player);
}

function resetStats(player) {
    player.setDynamicProperty("goe_spa_easy_quiz_result", 0);
    player.setDynamicProperty("goe_spa_medium_quiz_result", 0);
    player.setDynamicProperty("goe_spa_hard_quiz_result", 0);
}

async function playerFireworks(player, offset) {
    utils.runPlayerCommand(player, `particle goe_spa:fireworks ^${offset.x} ^${offset.y} ^${offset.z}`);
    utils.runPlayerCommand(player, "playsound firework.blast");
    utils.runPlayerCommand(player, "playsound firework.large_blast");
    utils.runPlayerCommand(player, "playsound firework.twinkle");
}