"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs = exports.KursblockungDynKurs = void 0;
const JavaObject_1 = require("../../java/lang/JavaObject");
const KursblockungOutputKursZuSchiene_1 = require("../../core/data/kursblockung/KursblockungOutputKursZuSchiene");
const System_1 = require("../../java/lang/System");
const LogLevel_1 = require("../../logger/LogLevel");
class KursblockungDynKurs extends JavaObject_1.JavaObject {
    guiID;
    representation;
    fachart;
    schienenLage;
    schienenLageSaveS;
    schienenLageSaveK;
    schienenLageFixiert;
    schienenFrei;
    schienenFreiSaveS;
    schienenFreiSaveK;
    schuelerAnz = 0;
    logger;
    /**
     * Der Kurs wählt eine zufällige Schienenlage und fügt sich selbst den
     * entsprechenden Schienen hinzu.
     *
     * @param pSchienenLage        Ein Array aller Schienen, in denen der Kurs
     *                             gerade liegt.
     * @param pSchienenLageFixiert Anzahl an Schienen in {@code pSchienenLage}, die
     *                             fixiert ist.
     * @param pSchienenFrei        Ein Array aller Schienen, in die der Kurs
     *                             wechseln könnte.
     * @param iKurs                Alle Informationen zu diesem Kurs. Das Objekt
     *                             stammt von der GUI.
     * @param pFachart             Die zu diesem Kurs zugehörige Fachart.
     * @param pLogger              Logger für Benutzerhinweise, Warnungen und
     *                             Fehler.
     */
    constructor(pSchienenLage, pSchienenLageFixiert, pSchienenFrei, iKurs, pFachart, pLogger) {
        super();
        this.schienenLage = pSchienenLage;
        this.schienenLageFixiert = pSchienenLageFixiert;
        this.schienenFrei = pSchienenFrei;
        this.guiID = iKurs.id;
        this.representation = iKurs.representation;
        this.fachart = pFachart;
        this.schuelerAnz = 0;
        this.logger = pLogger;
        this.schienenLageSaveS = Array(this.schienenLage.length).fill(null);
        this.schienenLageSaveK = Array(this.schienenLage.length).fill(null);
        for (let i = 0; i < this.schienenLage.length; i++) {
            this.schienenLageSaveS[i] = this.schienenLage[i];
            this.schienenLageSaveK[i] = this.schienenLage[i];
        }
        this.schienenFreiSaveS = Array(this.schienenFrei.length).fill(null);
        this.schienenFreiSaveK = Array(this.schienenFrei.length).fill(null);
        for (let i = 0; i < this.schienenFrei.length; i++) {
            this.schienenFreiSaveS[i] = this.schienenFrei[i];
            this.schienenFreiSaveK[i] = this.schienenFrei[i];
        }
        for (let i = 0; i < this.schienenLage.length; i++) {
            this.schienenLage[i].aktionKursHinzufuegen(this);
        }
    }
    toString() {
        return this.representation;
    }
    /**
     * Die Kurs-ID der GUI.
     *
     * @return Die Kurs-ID der GUI.
     */
    gibID() {
        return this.guiID;
    }
    /**
     * Eine String-Darstellung des Kurses, z.B. 'D;GK1'.
     *
     * @return Eine String-Darstellung des Kurses, z.B. 'D;GK1'.
     */
    gibRepresentation() {
        return this.representation;
    }
    /**
     * Liefert die zum Kurs zugehörige Fachart.
     *
     * @return Die zum Kurs zugehörige Fachart.
     */
    gibFachart() {
        return this.fachart;
    }
    /**
     * Liefert die aktuelle Anzahl an Schülern in diesem Kurs.
     *
     * @return Die aktuelle Anzahl an Schülern in diesem Kurs.
     */
    gibSchuelerAnzahl() {
        return this.schuelerAnz;
    }
    /**
     * Liefert {@code true} falls die Schienenlage des Kurses noch veränderbar ist.
     * Wenn der Kurs komplett fixiert ist, oder so viele Schienen gesperrt sind,
     * dass der Kurs keine Wahlmöglichkeit bezüglich seiner Schienen hat, dann ist
     * das Resultat {@code false}
     *
     * @return Liefert {@code true}, falls die Schienenlage des Kurses noch
     *         veränderbar ist.
     */
    gibHatFreiheitsgrade() {
        return (this.schienenLageFixiert < this.schienenLage.length) && (this.schienenFrei.length > 0);
    }
    /**
     * Liefert die aktuelle Schienenlage dieses Kurses.
     *
     * @return Ein Array, das angibt, in welchen Schienen der Kurs ist. Die Werte
     *         sind 0-indiziert.
     */
    gibSchienenLage() {
        let length = this.schienenLage.length;
        let lage = Array(length).fill(0);
        for (let i = 0; i < length; i++) {
            lage[i] = this.schienenLage[i].gibNr();
        }
        return lage;
    }
    /**
     * Liefert die Anzahl an Schienen, die dieser Kurs belegt.
     *
     * @return Die Anzahl an Schienen, die dieser Kurs belegt.
     */
    gibSchienenAnzahl() {
        return this.schienenLage.length;
    }
    /**
     * Speichert die aktuelle Lage der Schienen im Zustand S, um diese bei Bedarf
     * mit der Methode {@link #aktionZustandLadenS} zu laden.
     */
    aktionZustandSpeichernS() {
        System_1.System.arraycopy(this.schienenLage, 0, this.schienenLageSaveS, 0, this.schienenLage.length);
        System_1.System.arraycopy(this.schienenFrei, 0, this.schienenFreiSaveS, 0, this.schienenFrei.length);
    }
    /**
     * Speichert die aktuelle Lage der Schienen im Zustand K, um diese bei Bedarf
     * mit der Methode {@link #aktionZustandLadenK} zu laden.
     */
    aktionZustandSpeichernK() {
        System_1.System.arraycopy(this.schienenLage, 0, this.schienenLageSaveK, 0, this.schienenLage.length);
        System_1.System.arraycopy(this.schienenFrei, 0, this.schienenFreiSaveK, 0, this.schienenFrei.length);
    }
    /**
     * Lädt die zuvor mit der Methode {@link #aktionZustandSpeichernS} gespeicherte
     * Lage der Schienen.
     */
    aktionZustandLadenS() {
        this.aktionSchienenLageEntfernen();
        System_1.System.arraycopy(this.schienenLageSaveS, 0, this.schienenLage, 0, this.schienenLage.length);
        System_1.System.arraycopy(this.schienenFreiSaveS, 0, this.schienenFrei, 0, this.schienenFrei.length);
        this.aktionSchienenLageHinzufuegen();
    }
    /**
     * Lädt die zuvor mit der Methode {@link #aktionZustandSpeichernK} gespeicherte
     * Lage der Schienen.
     */
    aktionZustandLadenK() {
        this.aktionSchienenLageEntfernen();
        System_1.System.arraycopy(this.schienenLageSaveK, 0, this.schienenLage, 0, this.schienenLage.length);
        System_1.System.arraycopy(this.schienenFreiSaveK, 0, this.schienenFrei, 0, this.schienenFrei.length);
        this.aktionSchienenLageHinzufuegen();
    }
    /**
     * Verteilt den Kurs auf die Schienen zufällig.
     */
    aktionZufaelligVerteilen() {
        if (!this.gibHatFreiheitsgrade()) {
            return;
        }
        if (this.schuelerAnz > 0) {
            this.logger.log(LogLevel_1.LogLevel.ERROR, "Kurs.aktionZufaelligVerteilen: schuelerAnz > 0 (Ein Kurs mit SuS darf nicht verteilt werden)");
            return;
        }
        for (let i1 = this.schienenLageFixiert; i1 < this.schienenLage.length; i1++) {
            let i2 = (Math.random() * this.schienenFrei.length);
            let schiene1 = this.schienenLage[i1];
            let schiene2 = this.schienenFrei[i2];
            schiene1.aktionKursEntfernen(this);
            schiene2.aktionKursHinzufuegen(this);
            this.schienenLage[i1] = schiene2;
            this.schienenFrei[i2] = schiene1;
        }
    }
    /**
     * Setzt die Lage des Kurses auf die in der Liste übergebenen Schienen.
     *
     * @param pSchienenWahl Die Schienen (0-indiziert), in denen der Kurs liegen
     *                      soll.
     */
    aktionVerteileAufSchienen(pSchienenWahl) {
        for (let iLage = this.schienenLageFixiert; iLage < this.schienenLage.length; iLage++) {
            let schieneL = this.schienenLage[iLage];
            if (pSchienenWahl.contains(schieneL.gibNr())) {
                continue;
            }
            for (let iFrei = 0; iFrei < this.schienenFrei.length; iFrei++) {
                let schieneF = this.schienenFrei[iFrei];
                if (pSchienenWahl.contains(schieneF.gibNr())) {
                    schieneL.aktionKursEntfernen(this);
                    schieneF.aktionKursHinzufuegen(this);
                    this.schienenFrei[iFrei] = schieneL;
                    this.schienenLage[iLage] = schieneF;
                    break;
                }
            }
        }
    }
    /**
     * Speichert die aktuelle Kurs-Schiene-Zuordnung im Vector
     * {@code vKursZuSchiene}.
     *
     * @param vKursZuSchiene Diesem Vektor wird die aktuelle Kurszuordnung
     *                       hinzugefügt.
     */
    aktionOutputErzeugen(vKursZuSchiene) {
        let kursZuSchiene = new KursblockungOutputKursZuSchiene_1.KursblockungOutputKursZuSchiene();
        kursZuSchiene.kurs = this.guiID;
        kursZuSchiene.schienen = this.gibSchienenLage();
        vKursZuSchiene.add(kursZuSchiene);
    }
    /**
     * Entfernt einen Schüler aus diesem Kurs.
     */
    aktionSchuelerEntfernen() {
        this.fachart.aktionKursdifferenzEntfernen();
        this.schuelerAnz--;
        this.fachart.aktionSchuelerWurdeEntfernt();
        this.fachart.aktionKursdifferenzHinzufuegen();
    }
    /**
     * Fügt einen Schüler diesem Kurs hinzu.
     */
    aktionSchuelerHinzufügen() {
        this.fachart.aktionKursdifferenzEntfernen();
        this.schuelerAnz++;
        this.fachart.aktionSchuelerWurdeHinzugefuegt();
        this.fachart.aktionKursdifferenzHinzufuegen();
    }
    /**
     * Liefert TRUE, wenn die Schiene für den Kurs gesperrt wurde.
     *
     * @param pSchiene Die Schiene nach der gefragt wurde.
     *
     * @return TRUE, wenn die Schiene für den Kurs gesperrt wurde.
     */
    gibIstSchieneGesperrt(pSchiene) {
        for (let s of this.schienenLage) {
            if (s.gibNr() === pSchiene) {
                return false;
            }
        }
        for (let s of this.schienenFrei) {
            if (s.gibNr() === pSchiene) {
                return false;
            }
        }
        return true;
    }
    /**
     * Liefert TRUE, wenn die Schiene für den Kurs fixiert wurde.
     *
     * @param pSchiene Die Schiene nach der gefragt wurde.
     *
     * @return TRUE, wenn die Schiene für den Kurs fixiert wurde.
     */
    gibIstSchieneFixiert(pSchiene) {
        for (let iLage = 0; iLage < this.schienenLageFixiert; iLage++) {
            if (this.schienenLage[iLage].gibNr() === pSchiene) {
                return true;
            }
        }
        return false;
    }
    aktionSchienenLageHinzufuegen() {
        for (let i = 0; i < this.schienenLage.length; i++) {
            this.schienenLage[i].aktionKursHinzufuegen(this);
        }
    }
    aktionSchienenLageEntfernen() {
        for (let i = 0; i < this.schienenLage.length; i++) {
            this.schienenLage[i].aktionKursEntfernen(this);
        }
    }
    isTranspiledInstanceOf(name) {
        return ['de.nrw.schule.svws.core.kursblockung.KursblockungDynKurs'].includes(name);
    }
}
exports.KursblockungDynKurs = KursblockungDynKurs;
function cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs(obj) {
    return obj;
}
exports.cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs = cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs;
//# sourceMappingURL=KursblockungDynKurs.js.map