// Genus Spiel © 2025 by J. David Eisenberg is licensed under CC BY-NC-SA 4.0d
/*
 * In this version, you click the article first,
 * then the noun. Only when the noun is clicked do we
 * evaluate the answer. This simplifies things enormously.
 */


/*
 * Gibt random integer 0 <= resultat < max
 */
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function mischen(arr, anfang=0, ende=0) {
    var n = (ende == 0) ? arr.length: ende;
    for (var i = anfang; i < n - 1; i++) {
        j = i + getRandomInt(n - i);
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

let artikelGenusName = ["der", "die", "das"];

const MAX_RICHTIG = 10;
const MAX_FALSCH = 10;
const FALSCH_ANFANG = 10;
const WORT_INTERVAL = 3500;
const DROP_DURATION = 10000;

/* Info über Wort */
const NIVEAU = 0;
const ARTIKEL = 1;
const NOMEN = 2;

let spielInfo = {
    richtig: [],
    falsch: [],
    nomina: [],
    wörterIndex: 0,
    artikel: -1, // nichts gewählt
    nomen: null, // nichts gewählt
    timeout: null,
    spielend: false
};

const wordDrop = [
  { transform: "translate(0, 0)" },
  { transform: "translate(0, 400px)" }
];

const dropTiming = {
    duration: DROP_DURATION,
    fill: "forwards"
};

function setupArtikel(id, yPos) {
    let btn = document.getElementById(id);
    btn.style.top = yPos + "px";
    btn.addEventListener("click", wählArtikel);
}

function animationFertig(evt) {
    let anim = evt.target;
    let index = 0;
    while (index < spielInfo.nomina.length &&
           spielInfo.nomina[index].animation !== anim) {
        index++;
    }
    if (index < spielInfo.nomina.length) {
        abgelaufen(spielInfo.nomina[index]);
        let btn = spielInfo.nomina[index].button;
        btn.remove();
        spielInfo.nomina.splice(index, 1);
    }
}

function unHighlightArtikel() {
    if (spielInfo.artikel != -1) {
        document.getElementById("art" + spielInfo.artikel).style.backgroundColor="#ddd";
    }
    spielInfo.artikel = -1;
}

function abgelaufen(nomen) {
    let tabelleReihe = document.getElementById("resultTabelle").
        getElementsByTagName("td");
    let nRichtig = spielInfo.richtig.length;
    let nFalsch = spielInfo.falsch.length;

    let feedback = `${nomen.info[ARTIKEL]} ${nomen.info[NOMEN]}`;
    spielInfo.falsch.push(nomen.info);
    tabelleReihe.item(FALSCH_ANFANG + nFalsch).innerHTML = feedback;
    nFalsch++;

    if (spielInfo.falsch.length == MAX_FALSCH) {
        spielEnde();
    }
}

function auswerten() {
    let tabelleReihe = document.getElementById("resultTabelle").
        getElementsByTagName("td");
    let nRichtig = spielInfo.richtig.length;
    let nFalsch = spielInfo.falsch.length;

    let artikel = (spielInfo.artikel == -1) ? "" :
        artikelGenusName[spielInfo.artikel];
    let feedback = "";
    if (artikel == spielInfo.nomen.info[ARTIKEL]) {
        feedback = artikel + " " + spielInfo.nomen.info[NOMEN];
        spielInfo.richtig.push(feedback);
        tabelleReihe.item(nRichtig).innerHTML = feedback;
        nRichtig++;
    } else {
        if (artikel != "") {
            feedback = `<s>${artikel}</s> `;
        }
        feedback += `${spielInfo.nomen.info[ARTIKEL]} ${spielInfo.nomen.info[NOMEN]}`;
        spielInfo.falsch.push(spielInfo.nomen.info);
        tabelleReihe.item(10 + nFalsch).innerHTML = feedback;
        nFalsch++;
    }
    /* un-highlight Artikel */
    unHighlightArtikel();

    if (spielInfo.richtig.length == MAX_RICHTIG ||
        spielInfo.falsch.length == MAX_FALSCH) {
        spielEnde();
    }
}

function wählArtikel(evt) {
    let gewählt = parseInt(evt.target.id.replace("art",""));
    if (gewählt != spielInfo.artikel) {
        if (spielInfo.artikel != -1) {
            document.getElementById("art" + spielInfo.artikel).style.backgroundColor="#ddd";
        }
        document.getElementById("art" + gewählt).style.backgroundColor="#ff0";
        spielInfo.artikel = gewählt;
    }
}

function clickNomen(evt) {
    let btn = evt.target;
    let index = 0;

    while (index < spielInfo.nomina.length &&
           spielInfo.nomina[index].button !== btn) {
        index++;
    }
    if (index < spielInfo.nomina.length) {
        /* Highlight ändern */
        if (spielInfo.nomina[index] != spielInfo.nomen) {
            if (spielInfo.nomen != null) {
                spielInfo.nomen.button.style.backgroundColor="#ddd";
            }
            spielInfo.nomina[index].button.style.backgroundColor="#ff0";
        }

        spielInfo.nomen = spielInfo.nomina[index];
        auswerten();

        // no need to listen for a finish
        spielInfo.nomina[index].animation.removeEventListener("finish", animationFertig);
        spielInfo.nomina[index].animation.finish();
        let btn = spielInfo.nomina[index].button; // erinnere unser Knopf
        spielInfo.nomen = null;
        spielInfo.nomina.splice(index, 1); // aus von der array
        btn.remove();
    }
}

function spielEnde() {
    spielInfo.spielend = false;
    for (var index = 0; index < spielInfo.nomina.length; index++) {
        spielInfo.nomina[index].animation.removeEventListener("finish",animationFertig);
        spielInfo.nomina[index].animation.finish();
        let btn = spielInfo.nomina[index].button;
        btn.remove();
    }
    clearTimeout(spielInfo.timeout);
    spielInfo.timeout = null;
    let titel = document.getElementById("wonnen_verloren");
    if (spielInfo.richtig.length == MAX_RICHTIG) {
        titel.innerHTML = "Du hast gewonnen!";
    } else {
        titel.innerHTML = "Leider hast du verloren 🙁";
    }
    let dialog = document.getElementById("ergebnis");
    document.getElementById("überprüfen").style.display =
        (spielInfo.falsch.length == 0) ? "none" : "block";
    dialog.showModal();
}

function machWort() {
    let btn = document.createElement("button");
    let txt = document.createTextNode(wörter[spielInfo.wörterIndex][2]);
    btn.appendChild(txt);
    // console.log("Created", txt);
    btn.className = "nomen";
    btn.style.left = (getRandomInt(25) + 10) + "%";
    btn.addEventListener("click", clickNomen);
    /*
    let anim = btn.animate(wordDrop, dropTiming);
    */
    let keyFrames = new KeyframeEffect(btn,
                                       wordDrop, dropTiming);
    let anim = new Animation(keyFrames);
    anim.addEventListener("finish", animationFertig);
    document.getElementById("nomina").appendChild(btn);

    anim.play();
    spielInfo.nomina.push( {
        "button": btn,
        "animation": anim,
        "info": wörter[spielInfo.wörterIndex]
    });
    spielInfo.wörterIndex++;
    if (spielInfo.wörterIndex >= wörter.length) {
        mischen(wörter);
        spielInfo.wörterIndex = 0;
    }
    if (spielInfo.spielend) {
        spielInfo.timeout = setTimeout(machWort, WORT_INTERVAL);
    }
}

function neuerSpiel() {
   if (spielInfo.timeout != null) {
        clearTimeout(spielInfo.timeout);
    }
    spielInfo.timeout = null;
    let tabelleReihe = document.getElementById("resultTabelle").
        getElementsByTagName("td");
    for (let i = 0; i < MAX_RICHTIG; i++) {
        tabelleReihe.item(i).innerHTML = '&nbsp;';
    }
    for (let i = 0; i < MAX_FALSCH; i++) {
        tabelleReihe.item(FALSCH_ANFANG + i).innerHTML = '&nbsp;';
    }

    mischen(wörter);

    /*
     * Überprüfen?
     */
    let überprüfen = document.getElementById("überprüfen_box").checked;
    if (überprüfen && spielInfo.falsch.length > 0) {
        for (let fehler = 0; fehler < spielInfo.falsch.length; fehler++) {
            let erfunden = false;
            for (let wort = 0; wort < wörter.length && !erfunden; wort++) {
                if (wörter[wort][NOMEN] == spielInfo.falsch[fehler][NOMEN] &&
                    wörter[wort][ARTIKEL] == spielInfo.falsch[fehler][ARTIKEL] &&
                    wörter[wort][NIVEAU] == spielInfo.falsch[fehler][NIVEAU]) {
                    let temp = wörter[fehler];
                    wörter[fehler] = wörter[wort];
                    wörter[wort] = temp;
                    erfunden = true;
                }
            }
        }
        mischen(wörter, anfang=0, ende=spielInfo.falsch.length);
    }

    spielInfo.richtig = [];
    spielInfo.falsch = [];
    spielInfo.nomina = [];
    spielInfo.wörterIndex = 0;
    spielInfo.artikel = -1;
    spielInfo.nomen = null;
    spielInfo.spielend = true;

    machWort();
}

function setup() {
    setupArtikel("art0", 20);
    setupArtikel("art1", 80);
    setupArtikel("art2", 140);
    const closeButton = document.getElementById("schliessen");

    // "Close" button closes the dialog -- do this only once!!!
    closeButton.addEventListener("click", () => {
        document.getElementById("ergebnis").close();
        neuerSpiel();
    });

    neuerSpiel();
}
