// Irregular verbs © 2025 by J. David Eisenberg is licensed under CC BY-NC-SA 4.0
/*
 * for testing:
 * aktuellesProblem = {"artikel": "der/die/das/die", "artikelTyp": 0, "nomen": "Messer/Messer/n", "adjektiv": "braun", "kasus": 1, "genus": "n", "nummer": 0, "modell": dingeAkkModell.next().value};
 */
/*
 * Gibt random integer 0 <= resultat < max
 */
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

/*
 * Immer erhalten aus position 0, und entferenen
 * aus position 0.
 */
function IndexArr(initArr) {
    let arr = initArr;
    mischen(arr);

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

    function add(value){
        arr.push(value);
    }

    function erstEntfernen() {
        let wert = arr.splice(0, 1)[0];
        return wert;
    }

    function wertErhalten() {
        return arr[0];
    }

    return {
        arr,
        add,
        mischen,
        wertErhalten,
        erstEntfernen
    }
}

const verbList = [
    ["ab|biegen", "bog...ab", "abgebogen", "haben"],
    ["ab|schneiden", "schnitt...ab", "abgeschnitten", "haben"],
    ["an|bieten", "bot...an", "angeboten", "haben"],
    ["an|fangen", "fing...an", "angefangen", "haben"],
    ["an|rufen", "rief...an", "angerufen", "haben"],
    ["an|ziehen", "zog...an", "angezogen", "haben"],
    ["an|schreien", "schrie...an", "angeschrien", "haben"],
    ["b[a/ä]cken", "buk", "gebacken", "haben"],
    ["befehlen", "befahl", "befohlen", "haben"],
    ["befinden", "befand", "befunden", "haben"],
    ["begehen", "beging", "begangen", "haben"],
    ["beginnen", "begann", "begonnen", "haben"],
    ["beißen", "biss", "gebissen", "haben"],
    ["biegen", "bog", "gebogen", "haben"],
    ["bitten", "bat", "gebeten", "haben"],
    ["blasen", "blies", "geblasen", "haben"],
    ["bleiben", "blieb", "geblieben", "sein"],
    ["br[e/i]chen", "broch", "gebrochen", "haben"],
    ["ben[ehm/imm]en", "benahm", "benommen", "haben"],
    ["bieten", "bot", "geboten", "haben"],
    ["denken", "dachte", "gedacht", "haben"],
    ["dringen", "drang", "gedrungen", "sein"],
    ["durch|halten", "hielt...durch", "durchgehalten", "haben"],
    ["ein|gehen", "ging...ein", "eingegangen", "sein"],
    ["ein|greifen", "griff...ein", "eingegriffen", "haben"],
    ["ein|l[a/ä]den","lud...ein", "eingeladen", "haben"],
    ["ein|nehmen", "nahm...ein", "eingenommen", "haben"],
    ["empfangen", "empfing", "empfangen", "haben"],
    ["empfehlen", "empfahl", "empfohlen", "haben"],
    ["entscheiden","entschied","entscheiden","haben"],
    ["entspr[e/i]chen", "entsprach", "entsprochen", "haben"],
    ["erfinden", "erfand", "erfunden", "haben"],
    ["[e/i]ssen", "aß", "gegesssen", "haben"],
    ["fahren", "fuhr", "gefahren", "sein"],
    ["fallen", "fiel", "gefallen", "sein"],
    ["fangen", "fing", "gefangen", "haben"],
    ["fern|sehen", "sah...fern", "ferngesehen", "haben"],
    ["frei|l[a/ä]ssen", "ließ...frei", "freigelassen", "haben"],
    ["fressen", "fraß", "gefressen", "haben"],
    ["frieren", "fror", "gefroren", "haben"],
    ["geben", "gab", "gegeben", "haben"],
    ["gehen", "ging", "gegangen", "sein"],
    ["gelingen", "gelang", "gelungen", "sein"],
    ["genießen", "genoss", "genossen", "haben"],
    ["gewinnen", "gewann", "gewonnen", "haben"],
    ["giesen", "goss", "gegossen", "haben"],
    ["graben", "grub", "gegraben", "haben"],
    ["greifen", "griff", "gegriffen", "haben"],
    ["halten", "hielt", "gehalten", "haben"],
    ["h[e/i]lfen", "half", "geholfen", "haben"],
    ["heißen", "hieß", "geheißen", "haben"],
    ["kennen", "kannte", "gekannt", "haben"],
    ["kneifen", "kniff", "gekniffen", "haben"],
    ["kommen", "kam", "gekommen", "sein"],
    ["kriechen", "kroch", "gekrochen", "sein"],
    ["können", "konnte", "gekonnt", "haben"],
    ["l[a/ä]ssen", "ließ", "gelassen", "haben"],
    ["laufen", "lief", "gelaufen", "sein"],
    ["leiden", "litt", "gelitten", "haben"],
    ["lesen", "las", "gelesen", "haben"],
    ["liegen", "lag", "gelegen", "sein"],
    ["los|fahren", "fuhr...los", "losgefahren", "sein"],
    ["meiden", "mied", "gemieden", "haben"],
    ["messen", "maß", "gemessen", "haben"],
    ["nach|denken", "dachte...nach", "nachgedacht", "haben"],
    ["n[ehm/imm]en", "nahm", "genommen", "haben"],
    ["nennen", "nannte", "gennant", "haben"],
    ["pfeifen", "pfiff", "gepfiffen", "haben"],
    ["reiten", "ritt", "geritten", "sein"],
    ["rennen", "rannte", "gerannt", "sein"],
    ["riechen", "roch", "gerochen", "haben"],
    ["rufen", "rief", "gerufen", "haben"],
    ["scheinen", "schien", "geschienen", "haben"],
    ["schießen", "schoss", "geschossen", "haben"],
    ["schlafen", "schlief", "geschlafen", "haben"],
    ["schlagen", "schlug", "geschlagen", "haben"],
    ["schließen", "schloss", "geschlossen", "haben"],
    ["schmelzen", "schmolz", "geschmolzen", "haben"],
    ["schneiden", "schnitt", "geschnitten", "haben"],
    ["schreiben", "schrieb", "geschrieben", "haben"],
    ["schwimmen", "schwamm", "geschwommen", "sein"],
    ["*sein", "war", "gewesen", "sein"],
    ["senden", "sandte", "gesendet", "haben"],
    ["singen", "sang", "gesungen", "haben"],
    ["sinken", "sank", "gesunken", "sein"],
    ["sitzen", "saß", "gesessen", "sein"],
    ["spinnen", "spann", "gesponnen", "haben"],
    ["sprechen", "sprach", "gesprochen", "haben"],
    ["springen", "sprang", "gesprungen", "sein"],
    ["stehlen", "stahl", "gestohlen", "haben"],
    ["steigen", "stieg", "gestiegen", "sein"],
    ["sterben", "starb", "gestorben", "sein"],
    ["saufen", "soff", "gesoffen", "haben"],
    ["statt|finden", "fand...statt", "stattgefunden", "haben"],
    ["stechen", "stach", "gestochen", "haben"],
    ["stehen", "stand", "gestanden", "sein"],
    ["stoßen", "stieß", "gestoßen", "haben"],
    ["tragen", "trug", "getragen", "haben"],
    ["trinken", "trank", "getrunken", "haben"],
    ["über|geben", "gab...über", "übergegebn", "haben"],
    ["vor|schlagen", "schlug...vor", "vorgeschlagen", "haben"],
    ["*werden", "wurde", "geworden", "sein"]
];

let newVerbs;
let correctVerbs;
let wrong1Verbs;
let wrong2Verbs;
let wrong3Verbs;

const praesensVerben = {
    "sein": "bin/bist/ist/sind/seid/sind",
    "werden": "werde,wirst,wird,werden,werdet,werden"
}

const INFINITIV = 0;
const PRAETERITUM = 1;
const PERFEKT = 2;
const HILFSVERB = 3;

let bewertung = 0;
let nFrage = 0;
let nVersuch = 0;

let aktuellesProblem;

function wählOption(arr) {
    let n = getRandomInt(arr.length);
    return arr[n];
}

/*
 * Für Randomisierung, wir mischen
 * vor wir nehmen aus der List
 */
function nehmenAus(aList) {
    aList.mischen();
    return [aList, aList.wertErhalten()];
}

/*
 * Das problem ist gleich als die Lösung.
 */
function problemErstellen() {
    let sourceList;
    let sourcePosition;
    let verbInfo;
    /*
     * Repeat a past wrong answer?
     */
    let wiederholen = (getRandomInt(4) == 0);
    /* aber nur wenn es lohnt sich */
    if (wiederholen && (wrong3Verbs.arr.length + wrong2Verbs.arr.length +
            wrong1Verbs.arr.length + correctVerbs.arr.length) < 5)
    {
        wiederholen = false;
    }

    if (wiederholen) {
        // console.log("wiederholen");
        if (wrong3Verbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(wrong3Verbs);
            // console.log("got", verbInfo, "from wrong3");
        } else if (wrong2Verbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(wrong2Verbs);
            // console.log("got", verbInfo, "from wrong2");
        } else if (wrong1Verbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(wrong1Verbs);
            // console.log("got", verbInfo, "from wrong1");
        } else if (correctVerbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(correctVerbs);
            // console.log("got", verbInfo, "from correct");
        }
    } else {
        if (newVerbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(newVerbs);
            // console.log("got", verbInfo, "from new verbs");
        } else if (wrong3Verbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(wrong3Verbs);
            // console.log("got", verbInfo, "from wrong3");
        } else if (wrong2Verbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(wrong2Verbs);
            // console.log("got", verbInfo, "from wrong2");
        } else if (wrong1Verbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(wrong1Verbs);
            // console.log("got", verbInfo, "from wrong1");
        } else if (correctVerbs.arr.length > 0) {
            [sourceList, verbInfo] = nehmenAus(correctVerbs);
            // console.log("got", verbInfo, "from correct");
        }
    }

    let anzeige = wählOption([INFINITIV,PRAETERITUM,PERFEKT]);
    let infinitiv = verbInfo[INFINITIV];
    let praeteritum = verbInfo[PRAETERITUM];
    let perfekt = verbInfo[PERFEKT];
    let hilfsverb = verbInfo[HILFSVERB];

    let idx = infinitiv.indexOf('[');
    if (idx >= 0) {
        let idx2 = infinitiv.indexOf(']');
        let base = infinitiv.substring(idx + 1, idx2).split('/')[0]
        infinitiv = infinitiv.substring(0, idx) + base + infinitiv.substring(idx2 + 1);
    }
    infinitiv = infinitiv.replaceAll("|", "").replaceAll("*","");
    return {
        "verb": verbInfo[anzeige],
        "infinitiv": infinitiv,
        "praeteritum": praeteritum,
        "perfekt": perfekt,
        "hilfsverb": hilfsverb,
        "anzeige": anzeige,
        "sourceList": sourceList
    };
}

function problemAnzeigen(problem) {
    if (problem.anzeige == INFINITIV) {
        insertHTML(problem.infinitiv, "infinitivText");
        setClass("infinitivText", "sichtbar");
        setClass("infinitivInput", "unsichtbar");
        setClass("praeteritumInput", "sichtbar");
        setClass("perfektInput", "sichtbar");
    }
    else if (problem.anzeige == PRAETERITUM) {
        insertHTML(problem.praeteritum, "praeteritumText");
        setClass("praeteritumText", "sichtbar");
        setClass("praeteritumInput", "unsichtbar");
        setClass("infinitivInput", "sichtbar");
        setClass("perfektInput", "sichtbar");
    } else { // müss Perfket sein
        insertHTML(problem.perfekt, "perfektText");
        setClass("perfektText", "sichtbar");
        setClass("perfektInput", "unsichtbar");
        setClass("infinitivInput", "sichtbar");
        setClass("praeteritumInput", "sichtbar");
    }
}

function canonical(str) {
    str = str.trim().replaceAll(".", " ").replaceAll(/\s+/g, " ")
    str = str.replaceAll("ß", "ss");
    str = str.replaceAll("ä", "ae").replaceAll("ü", "ue").replaceAll("ö", "oe");
    str = str.replaceAll("Ä", "Ae").replaceAll("Ü", "Ue").replaceAll("Ö", "Oe");
    return str;
}

function machHinweise(problem, antwortTeile, artikelOK, adjOK, nomenOK) {
    let ergebnis = "<div class=\"hinweise\">";
    ergebnis += "</div>";
    return ergebnis;
}

function auswerten(evt) {
    evt.preventDefault();
    let infinitivOK = true;
    let pretaeritumOK = true;
    let perfektOK = true;
    let hilfsverbOK = true;
    let nFehler = 0;
    let feedbackStr = "";

    if (aktuellesProblem.anzeige == INFINITIV) {
        praeteritumOK = (canonical(aktuellesProblem.praeteritum) ==
            canonical(document.getElementById("praeteritumInput").value));
        perfektOK = (canonical(aktuellesProblem.perfekt) ==
            canonical(document.getElementById("perfektInput").value));
        nFehler += fehlerWert("praeteritum", praeteritumOK);
        nFehler += fehlerWert("perfekt", perfektOK);
    } else if (aktuellesProblem.anzeige == PRAETERITUM) {
        infinitivOK = (canonical(aktuellesProblem.infinitiv) ==
            canonical(document.getElementById("infinitivInput").value))
        perfektOK = (canonical(aktuellesProblem.perfekt) ==
            canonical(document.getElementById("perfektInput").value));
        nFehler += fehlerWert("infinitiv", infinitivOK);
        nFehler += fehlerWert("perfekt", perfektOK);
    } else { // Perfekt
        infinitivOK = (canonical(aktuellesProblem.infinitiv) ==
            canonical(document.getElementById("infinitivInput").value))
        praeteritumOK = (canonical(aktuellesProblem.praeteritum) ==
            canonical(document.getElementById("praeteritumInput").value));
        nFehler += fehlerWert("infinitiv", infinitivOK);
        nFehler += fehlerWert("praeteritum", praeteritumOK);
    }

    hilfsverbOK = aktuellesProblem.hilfsverb == document.getElementById("hilfsverbOptionen").value;
    nFehler += fehlerWert ("hilfsverb", hilfsverbOK);

    if (nFehler == 0) {
        let congrats = ["Richtig!", "Gut gemacht!", "Ach, wie gut!", "Exzellent!",
            "Ausgezeichnet!"];
        if (nVersuch == 0) {
            feedbackStr += `${congrats[getRandomInt(congrats.length)]}`;
        } else {
            feedbackStr += `<span class="normal">Richtig.</span>`;
        }

        if (nVersuch == 0) {
            bewertung += 1;
        } else {
            bewertung += 0.5;
        }

        insertHTML(euroFormat(bewertung), "korrect");
        insertHTML(nFrage, "total");
        insertHTML(feedbackStr, "feedback");

        document.getElementById("überprüfen").disabled = true;

        let entfernt = aktuellesProblem.sourceList.erstEntfernen();
        // console.log("entfernt", entfernt);

        if (nVersuch == 0) {
            // console.log("Hinzugefügt zu correct");
            correctVerbs.add(entfernt);
        } else if (nVersuch == 1) {
            // console.log("Hinzugefügt zu wrong1");
            wrong1Verbs.add(entfernt);
        } else if (nVersuch == 2) {
            // console.log("Hinzugefügt zu wrong2");
            wrong2Verbs.add(entfernt);
        } else {
            // console.log("Hinzugefügt zu wrong3");
            wrong3Verbs.add(entfernt);
        }
    } else {
        if (nVersuch == 2) {
            feedbackStr = `Lösung: ${aktuellesProblem.infinitiv} / ${aktuellesProblem.praeteritum} / ` +
                `${aktuellesProblem.perfekt} / ${aktuellesProblem.hilfsverb}`;
            document.getElementById("überprüfen").disabled = true;

            let entfernt = aktuellesProblem.sourceList.erstEntfernen();
            // console.log("entfernt", entfernt);
            // console.log("Hinzugefügt zu wrong3")
            wrong3Verbs.add(entfernt);
        } else {
            feedbackStr = "Versuchen Sie wieder, bitte.";
            nVersuch++;
        }
        insertHTML(feedbackStr, "feedback");
    }

}


function insertHTML(text, id) {
    document.getElementById(id).innerHTML = text;
}

function euroFormat(n) {
    let ganzeZahl = Math.floor(n);
    let fraktion = n - ganzeZahl;
    if (fraktion == 0) {
        return n.toString();
    } else {
        return n.toString().replace('.', ',');
    }
}

function setClass(id, className) {
    document.getElementById(id).className = className;
}

function fehlerWert(id, isOK) {
    let n = 0;
    if (isOK) {
        setClass(id, "correct");
    } else {
        setClass(id, "wrong");
        n = 1;
    }
    return n;
}

function neuesProblem(evt) {
    if (evt != null) {
        evt.preventDefault();
    }
    nVersuch = 0;
    nFrage++;
    aktuellesProblem = problemErstellen();
    insertHTML('\u00a0', "infinitivText");
    insertHTML('\u00a0', "praeteritumText");
    insertHTML('\u00a0', "perfektText");

    setClass("infinitivText", "unsichtbar");
    setClass("infinitivInput", "unsichtbar");
    setClass("praeteritumText", "unsichtbar");
    setClass("praeteritumInput", "unsichtbar");
    setClass("perfektText", "unsichtbar");
    setClass("perfektInput", "unsichtbar");

    document.getElementById("infinitivInput").value = "";
    document.getElementById("praeteritumInput").value = "";
    document.getElementById("perfektInput").value = "";

    setClass("infinitiv", "keinAntwort");
    setClass("praeteritum", "keinAntwort");
    setClass("perfekt", "keinAntwort");
    setClass("hilfsverb", "keinAntwort");

    document.getElementById("hilfsverbOptionen").value = "---";

    problemAnzeigen(aktuellesProblem);

    insertHTML("\u00a0", "feedback");
    document.getElementById("überprüfen").disabled = false;
}


function setup() {
    /*
     * Lass allein das Original!!!!
     */
    let clone = [];
    for (let i = 0; i < verbList.length; i++) {
        clone.push(verbList[i]);
    }

    newVerbs = IndexArr(clone);
    correctVerbs = IndexArr([]);
    wrong1Verbs = IndexArr([]);
    wrong2Verbs = IndexArr([]);
    wrong3Verbs = IndexArr([]);

    neuesProblem(null);
    document.getElementById("überprüfen").addEventListener("click", auswerten);
    document.getElementById("weiter").addEventListener("click", neuesProblem);
}
