"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cast_de_nrw_schule_svws_core_kursblockung_satsolver_Heap = exports.Heap = void 0;
const JavaObject_1 = require("../../../java/lang/JavaObject");
const Arrays_1 = require("../../../java/util/Arrays");
class Heap extends JavaObject_1.JavaObject {
    _data;
    _size = 0;
    /**
     * Konstruktor.
     */
    constructor() {
        super();
        this._data = Array(1).fill(null);
        this._size = 0;
    }
    toString() {
        return "Heap: " + Arrays_1.Arrays.toString(Arrays_1.Arrays.copyOf(this._data, this._size)).valueOf();
    }
    /**
     * Überprüft, ob der Heap leer ist.
     *
     * @return TRUE, wenn der Heap leer ist.
     */
    isEmpty() {
        return this._size === 0;
    }
    /**
     * Liefert das oberste (beste) Element des Heaps mit hoher Wahrscheinlichkeit.
     *
     * @return Liefert das oberste (beste) Element des Heaps mit hoher Wahrscheinlichkeit.
     */
    top() {
        let index = 0;
        while ((Math.random() < 0.1) && (index + 1 < this._size)) {
            index++;
        }
        return this._data[index];
    }
    /**
     * Liefert die Anzahl an Elementen im Heap.
     *
     * @return Die Anzahl an Elementen im Heap.
     */
    size() {
        return this._size;
    }
    /**
     * Fügt die Variable "var" dem Heap hinzu. Nach dem Einfügen kennt die Variable
     * mit {@link Variable#index} ihre eigene Position in diesem Heap.
     *
     * @param pVar Die einzufügende Variable.
     */
    insert(pVar) {
        if (this._size === this._data.length) {
            this._data = Arrays_1.Arrays.copyOf(this._data, 2 * this._size);
        }
        let insertI = this._size;
        while (insertI > 0) {
            let parentI = Math.trunc((insertI - 1) / 2);
            let parentV = this._data[parentI];
            if (pVar.isBetterThan(parentV)) {
                this._data[insertI] = parentV;
                parentV.index = insertI;
                insertI = parentI;
            }
            else {
                break;
            }
        }
        this._data[insertI] = pVar;
        pVar.index = insertI;
        this._size++;
    }
    /**
     * Entfernt die Variable pVar vom Heap. Dabei wird zunächst mit Hilfe von
     * {@link Variable#index} die Position bestimmt. Anschließend wird der Heap so
     * transformiert, dass die Variable entfernt werden kann.
     *
     * @param pVar Die zu entfernende Variable.
     */
    remove(pVar) {
        this._size--;
        let lastV = this._data[this._size];
        if (lastV === pVar) {
            return;
        }
        let currentI = pVar.index;
        if (this._data[pVar.index] !== pVar) {
            console.log(JSON.stringify("FEHLER: Die Variable " + pVar + " ist nicht beim Index " + pVar.index + "!"));
        }
        while (currentI > 0) {
            let parentI = Math.trunc((currentI - 1) / 2);
            this._data[currentI] = this._data[parentI];
            this._data[currentI].index = currentI;
            currentI = parentI;
        }
        let parentI = 0;
        let childI = 1;
        while (childI < this._size) {
            if (childI + 1 < this._size) {
                if (this._data[childI + 1].isBetterThan(this._data[childI])) {
                    childI = childI + 1;
                }
            }
            let child = this._data[childI];
            if (child.isBetterThan(lastV)) {
                this._data[parentI] = child;
                child.index = parentI;
                parentI = childI;
                childI = parentI * 2 + 1;
            }
            else {
                break;
            }
        }
        this._data[parentI] = lastV;
        lastV.index = parentI;
    }
    /**
     * Falls sich die Variable pVar im Heap befindet, wird sie entfernt und direkt
     * wieder hinzugefügt. Diese Methode muss aufgerufen werden, sobald die Variable
     * eine neue Bewertung erhalten hat.
     *
     * @param pVar Die Variable, deren Bewertung sich geändert hat.
     */
    update(pVar) {
        if (pVar.index >= 0) {
            this.remove(pVar);
            if (pVar.negation !== null)
                this.remove(pVar.negation);
            this.insert(pVar);
            if (pVar.negation !== null)
                this.insert(pVar.negation);
        }
    }
    isTranspiledInstanceOf(name) {
        return ['de.nrw.schule.svws.core.kursblockung.satsolver.Heap'].includes(name);
    }
}
exports.Heap = Heap;
function cast_de_nrw_schule_svws_core_kursblockung_satsolver_Heap(obj) {
    return obj;
}
exports.cast_de_nrw_schule_svws_core_kursblockung_satsolver_Heap = cast_de_nrw_schule_svws_core_kursblockung_satsolver_Heap;
//# sourceMappingURL=Heap.js.map