// dialog.js
// Generic code to show messages with a dismiss button
// There are two functions available.
//
// function showDialog(text, callback /* optional */)
//    Shows the text in a dialog. It has an optional callback argument.
//    If the optional callback is provided, it is called when the OK button is clicked.
//
//  async function showDialogAsync(text)
//    Shows the text in a dialog. This returns a promise, which is resolved to true
//    when the OK button is clicked. This form is thenable can be used in an await statement.

import $ from "./jquery.module.js";
import {convertDisplayNameToID} from "./regularize_string.js";
import * as language from "./language.js";
import * as caves_and_trees from "./caves_and_trees_lib.js";

function simpleButton(buttonDiv) {
    let btn = {
        resolver: null,
        buttonClick: function() {
            const {promise, resolve} = Promise.withResolvers();
            this.resolver = resolve;
            return promise;
        }
    };
    const $buttonDiv = (buttonDiv instanceof $) ? buttonDiv : $(buttonDiv);
    $buttonDiv.off("click").on("click", {btn}, () => {
        btn.resolver?.();
        btn.resolver = null;
    });
    return btn;
}

// Looks for an element with an ID of wrapper, which should be the top level div in all blocks ;
function getDialogWrapper() {
    let dialogWrapper = $("#wrapper");
    if (dialogWrapper.length === 0) {
        dialogWrapper = $(".dialog-wrapper");
    }
    return dialogWrapper;
}

// When the okbutton is clicked, the dialog box will be removed and the call back executed, which is usually to go to a new page ;
function okButton(evt, callback) {
    $(".dialog7gen_holder").remove();
    callback?.();
}

function okButtonResolve(evt, resolve) {
    $(".dialog7gen_holder").remove();
    resolve(true);
}

// CREATES A DIV THAT HAS THE MESSAGE PASSED TO IT AND AN OK BUTTON ;
function dialogMessageHTML(arg) {
    let argObj;
    if (typeof arg === "string") {
        argObj = {text: arg};
    }
    else if (typeof arg === "object") {
        argObj = arg;
    }
    else {
        return null;
    }
    const {text, lang1, lang2, langBtn1, langBtn2} = argObj;

    let messageFragment;
    let okButtonFragment;
    let displayLang1 = "";
    let displayLang2 = "d-none";
    switch (language.currentLanguage()) {
        case "lang1":
            displayLang1 = "";
            displayLang2 = "d-none";
            break;
        case "lang2":
            displayLang1 = "d-none";
            displayLang2 = "";
            break;
    }
    if (lang1 && lang2) {
        messageFragment = `
                <div class="message7gen lang1 ${displayLang1}">
                    ${lang1}
                </div>
                <div class="message7gen lang2 ${displayLang2}">
                    ${lang2}
                </div>
        `;
    }
    else if (lang1) {
        messageFragment = `
                <div class="message7gen">
                    ${lang1}
                </div>
        `;
    }
    else { // message must be in text
        messageFragment = `
                <div class="message7gen">
                    ${text}
                </div>
        `;
    }
    if (langBtn1 && langBtn2) {
        okButtonFragment = `
                <button class="okbutton7gen lang1 ${displayLang1}">
                    ${langBtn1}
                </button>
                <button class="okbutton7gen lang2 ${displayLang2}">
                    ${langBtn2}
                </button>
        `;
    }
    else if (langBtn1) {
        okButtonFragment = `
                <button class="okbutton7gen">
                    ${langBtn1}
                </button>
        `;
    }
    else { // No button text was given, just make it "OK"
        okButtonFragment = `
                <button class="okbutton7gen">
                    OK
                </button>
        `;
    }
    return `
        <div class="dialog7gen_holder container">
            <div class="dialog7gen">
               ${messageFragment}
                <div class="okbuttonrow">
<!--                    <button class="okbutton7gen"><img src="../../game_theme/theme/icons/next.png" alt="arrow pointing right"</button>-->
                    ${okButtonFragment}
                </div>
                <div class="choice-button-row"></div>
            </div>
        </div>
    `;

}

function showDialog(text, callback /* optional */) {
    const $wrapper = getDialogWrapper();
    $wrapper.append(dialogMessageHTML(text));
    $(".choice-button-row").hide();
    $(".okbutton7gen").on("click", (evt)=>okButton(evt, callback));
}

async function showDialogAsync(text) {
    const $wrapper = getDialogWrapper();
    $wrapper.append(dialogMessageHTML(text));
    $(".choice-button-row").hide();

    return new Promise((resolve, reject) => {
        $(".okbutton7gen").on("click", (evt) => okButtonResolve(evt, resolve));
    });
}

async function showChoiceDialogAsync(message, choices) {
    // "message" is displayed at the top of the dialog
    //
    // "choices" is an array of strings that are used as labels for buttons
    // at the bottom of the dialog. When a button is pressed, the function returns
    // the string corresponding to the clicked button.

    const $wrapper = getDialogWrapper();
    $wrapper.append(dialogMessageHTML(message));
    $(".okbuttonrow").hide();

    const $buttonRow = $(".choice-button-row");
    const {promise, resolve} = Promise.withResolvers();

    for (const choice of choices) {
        const btnClass = convertDisplayNameToID({prefix: "btnClass", displayName: choice});
        $buttonRow.append(`<button class="${btnClass} okbutton7gen">${choice}</button>`);
        $(`.${btnClass}`).on("click", (evt) => resolve(choice));
    }

    const answer = await promise;
    $(".dialog7gen_holder").remove();
    return answer;
}

function showPersistentMessage(message) {
    // This dialog stays up until you dismiss it. The dismiss function
    // is returned.
    const $wrapper = getDialogWrapper();
    $wrapper.append(dialogMessageHTML(message));
    $(".choice-button-row").hide();
    $(".okbuttonrow").hide();

    return () => $(".dialog7gen_holder").remove();
}

const answerLabels = "abcdefghijklmnopqrstuvwxyz".split("");

async function showMultipleChoiceQuestion({question, answers, rightAnswerFlag = "*", parentDiv}) {
    let displayedQuestion = `<div class="question-multiple-7gen">Q: ${question}${question.endsWith("?") ? "" : "?"}</div>`;
    let correctAnswer;
    for (let [index, answer] of answers.entries()) {
        const label = answerLabels[index];
        if (answer[0] === rightAnswerFlag) {
            answer = answer.substring(1);
            correctAnswer = {label, index};
        }
        const id7gen = `7gen-${label}`;
        displayedQuestion += `
            <div class="answer-multiple-7gen">
                <input type="radio" name="choice-7gen" id="${id7gen}" value="${index}">
                <label for="${id7gen}">${answer}</label>
            </div>
        `;
    }
    displayedQuestion += `<button id="submit-choice-7gen" class="okbutton7gen">OK</button>`;

    let answerWasSelected = false;
    let selectedVal = null;
    while (!answerWasSelected) {
        $(`#${parentDiv}`).html(displayedQuestion);
        // $("#submit-choice-7gen").on("click", submitAnswer);
        let btn = simpleButton($("#submit-choice-7gen"));
        await btn.buttonClick();
        let selected = $("input[type='radio'][name='choice-7gen']:checked");
        if (selected.length > 0) {
            selectedVal = parseInt(selected.val(), 10);
            answerWasSelected = true;
        }
        else {
            await showDialogAsync("You must select an answer");
        }
    }

    return {
        selectedVal,
        correct: (correctAnswer.index === selectedVal)
    }
}

async function showTextEntryDialog({prompt, parentDiv}) {
    let displayedPrompt = `<div class="question-7gen">${prompt}</div>`;
    displayedPrompt += `<label for="answer-7gen"></label>Enter answer:<input name="answer-7gen" id="answer-7gen" type="text">`;
    displayedPrompt += `<div><button id="submit-answer-7gen" class="okbutton7gen">Submit</button></div>`;
    $(`#${parentDiv}`).html(displayedPrompt);

    let answerWasSubmitted = false;
    let answer = null;
    let entry = null;
    while (!answerWasSubmitted) {
        let btn = simpleButton($("#submit-answer-7gen"));
        await btn.buttonClick();
        answer = $("#answer-7gen").val();
        if (answer === null || answer === "") {
            await showDialogAsync("You must select an answer");
        }
        else {
            answerWasSubmitted = true;
        }
    }

    return answer;
}

export {showDialog, showDialogAsync, showChoiceDialogAsync, showPersistentMessage, showMultipleChoiceQuestion, showTextEntryDialog};
