import { JavaObject, cast_java_lang_Object } from '../../java/lang/JavaObject';
import { KursblockungDynDaten, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynDaten } from '../../core/kursblockung/KursblockungDynDaten';
import { KursblockungAlgorithmusK, cast_de_nrw_schule_svws_core_kursblockung_KursblockungAlgorithmusK } from '../../core/kursblockung/KursblockungAlgorithmusK';
import { Logger, cast_de_nrw_schule_svws_logger_Logger } from '../../logger/Logger';
import { System, cast_java_lang_System } from '../../java/lang/System';

export class KursblockungAlgorithmusKFachwahlmatrix extends KursblockungAlgorithmusK {


	/**
	 * Im Konstruktor kann die Klasse die jeweiligen Datenstrukturen aufbauen. Kurse
	 * dürfen in diese Methode noch nicht auf Schienen verteilt werden.
	 * 
	 * @param logger Logger für Benutzerhinweise, Warnungen und Fehler.
	 * @param dynDat Die dynamischen Blockungsdaten.
	 */
	public constructor(logger : Logger, dynDat : KursblockungDynDaten) {
		super(logger, dynDat);
	}

	/**
	 * Der Algorithmus entfernt zunächst alle SuS aus ihren Kursen. Anschließend
	 * werden die Kurse zufällig verteilt.
	 */
	public berechne(pMaxTimeMillis : number) : void {
		if (this.dynDaten.gibKurseDieFreiSindAnzahl() === 0) {
			return;
		}
		let timeStart : number = System.currentTimeMillis();
		this.dynDaten.aktionSchuelerAusAllenKursenEntfernen();
		this.dynDaten.aktionKurseFreieZufaelligVerteilen();
		this.dynDaten.aktionZustandSpeichernK();
		let countKeineVerbesserung : number = 0;
		while (System.currentTimeMillis() - timeStart < pMaxTimeMillis) {
			if (this.berechneSchritt()) {
				countKeineVerbesserung = 0;
			} else {
				countKeineVerbesserung++;
				if (countKeineVerbesserung === 10000) {
					break;
				}
			}
		}
	}

	/**
	 * Die Lage einiger Kurse wird verändert. Falls sich die Bewertung
	 * verschlechter, wird die Veränderung rückgängig gemacht.
	 * 
	 * @return TRUE, falls sich die Bewertung verbessert hat.
	 */
	private berechneSchritt() : boolean {
		let maxChanges : number = 1;
		while (Math.random() < 0.5) {
			maxChanges++;
		}
		for (let changes : number = 0; changes < maxChanges; changes++){
			this.dynDaten.aktionKursFreienEinenZufaelligVerteilen();
			if (this.dynDaten.gibBewertungJetztBesserAlsK() > 0) {
				this.dynDaten.aktionZustandSpeichernK();
				return true;
			}
		}
		this.dynDaten.aktionZustandLadenK();
		return false;
	}

	isTranspiledInstanceOf(name : string): boolean {
		return ['de.nrw.schule.svws.core.kursblockung.KursblockungAlgorithmusKFachwahlmatrix', 'de.nrw.schule.svws.core.kursblockung.KursblockungAlgorithmusK'].includes(name);
	}

}

export function cast_de_nrw_schule_svws_core_kursblockung_KursblockungAlgorithmusKFachwahlmatrix(obj : unknown) : KursblockungAlgorithmusKFachwahlmatrix {
	return obj as KursblockungAlgorithmusKFachwahlmatrix;
}
