import { JavaObject, cast_java_lang_Object } from '../../java/lang/JavaObject';
import { KursblockungDynStatistik, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynStatistik } from '../../core/kursblockung/KursblockungDynStatistik';
import { KursblockungDynKurs, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs } from '../../core/kursblockung/KursblockungDynKurs';
import { JavaString, cast_java_lang_String } from '../../java/lang/JavaString';
import { System, cast_java_lang_System } from '../../java/lang/System';

export class KursblockungDynFachart extends JavaObject {

	private readonly nr : number;

	private readonly representation : String;

	private kursArr : Array<KursblockungDynKurs>;

	private schuelerMax : number = 0;

	private kurseMax : number = 0;

	private schuelerAnzNow : number = 0;

	private readonly statistik : KursblockungDynStatistik;


	/**
	 * @param pNr             Eine laufende Nummer (ID) für alle Facharten.
	 * @param pRepresentation Eine String-Darstellung der Fachart, z.B. 'D;LK'.
	 * @param pStatistik      Dem Statistik-Objekt wird eine Veränderung der
	 *                        Kursdifferenz mitgeteilt.
	 */
	public constructor(pNr : number, pRepresentation : String, pStatistik : KursblockungDynStatistik) {
		super();
		this.nr = pNr;
		this.representation = pRepresentation;
		this.statistik = pStatistik;
		this.kursArr = Array(0).fill(null);
		this.kurseMax = 0;
		this.schuelerMax = 0;
		this.schuelerAnzNow = 0;
	}

	/**
	 * Durch das Überschreiben dieser Methode, liefert dieses Objekt eine
	 * automatische String-Darstellung, beispielsweise 'D;LK'.
	 */
	public toString() : String {
		return this.representation;
	}

	/**
	 * Liefert die Nummer dieser Fachart.
	 * 
	 * @return Die Nummer dieser Fachart.
	 */
	public gibNr() : number {
		return this.nr;
	}

	/**
	 * Liefert die maximale Anzahl ({@link #schuelerMax}) an SuS, die dieser Fachart
	 * zugeordnet sein können. Das ist die Anzahl der Fachwahlen.
	 * 
	 * @return Die Anzahl der SuS, die diese Fachart gewählt haben.
	 */
	public gibSchuelerMax() : number {
		return this.schuelerMax;
	}

	/**
	 * Liefert die aktuelle Anzahl ({@link #schuelerAnzNow}) an SuS, die dieser
	 * Fachart zugeordnet sind.
	 * 
	 * @return Die Anzahl der SuS, die diese Fachart aktuell zugeordnet sind.
	 */
	public gibSchuelerZordnungen() : number {
		return this.schuelerAnzNow;
	}

	/**
	 * Liefert die Anzahl der Kurse die dieser Fachart zugeordnet sind.
	 * 
	 * @return Die Anzahl der Kurse die dieser Fachart zugeordnet sind.
	 */
	public gibKurseMax() : number {
		return this.kurseMax;
	}

	/**
	 * Liefert die aktuell größte Kursdifferenz.
	 * 
	 * @return Die aktuell größte Kursdifferenz.
	 */
	public gibKursdifferenz() : number {
		return this.kursArr[this.kursArr.length - 1].gibSchuelerAnzahl() - this.kursArr[0].gibSchuelerAnzahl();
	}

	/**
	 * Liefert das Array aller Kurse dieser Fachart.
	 * 
	 * @return Das Array aller Kurse dieser Fachart.
	 */
	public gibKurse() : Array<KursblockungDynKurs> {
		return this.kursArr;
	}

	/**
	 * Ordnet alle Kurse der Fachart zu. Die Kurse haben noch keine SuS und sind
	 * somit automatisch sortiert.
	 * 
	 * @param pKursArr Alle Kurse der Fachart.
	 */
	public aktionSetKurse(pKursArr : Array<KursblockungDynKurs>) : void {
		this.kursArr = pKursArr;
	}

	/**
	 * Erhöht die Anzahl ({@link #schuelerMax}) an SuS, die diese Fachart gewählt
	 * haben um 1.
	 */
	public aktionMaxSchuelerErhoehen() : void {
		this.schuelerMax++;
	}

	/**
	 * Erhöht die Anzahl ({@link #kurseMax}) an Kursen, die zu dieser Fachart
	 * gehören.
	 */
	public aktionMaxKurseErhoehen() : void {
		this.kurseMax++;
	}

	/**
	 * Muss aufgerufen werden, bevor die Schüleranzahl eines Kurses verändert wird.
	 */
	public aktionKursdifferenzEntfernen() : void {
		this.statistik.aktionKursdifferenzEntfernen(this.gibKursdifferenz());
	}

	/**
	 * Muss aufgerufen werden, nachdem die Schüleranzahl eines Kurses verändert
	 * wird.
	 */
	public aktionKursdifferenzHinzufuegen() : void {
		this.statistik.aktionKursdifferenzHinzufuegen(this.gibKursdifferenz());
	}

	/**
	 * Erhöht die Anzahl ({@link #schuelerAnzNow}) an Schülern, die dieser Fachart
	 * momentan zugeordnet sind um 1. Die Aufru
	 */
	public aktionSchuelerWurdeHinzugefuegt() : void {
		this.schuelerAnzNow++;
		for (let i : number = 1; i < this.kursArr.length; i++){
			let kursL : KursblockungDynKurs = this.kursArr[i - 1];
			let kursR : KursblockungDynKurs = this.kursArr[i];
			if (kursL.gibSchuelerAnzahl() > kursR.gibSchuelerAnzahl()) {
				this.kursArr[i - 1] = kursR;
				this.kursArr[i] = kursL;
			}
		}
	}

	/**
	 * Verringert die Anzahl ({@link #schuelerAnzNow}) an SuS, die dieser Fachart
	 * momentan zugeordnet sind um 1.
	 */
	public aktionSchuelerWurdeEntfernt() : void {
		this.schuelerAnzNow--;
		for (let i : number = this.kursArr.length - 1; i >= 1; i--){
			let kursL : KursblockungDynKurs = this.kursArr[i - 1];
			let kursR : KursblockungDynKurs = this.kursArr[i];
			if (kursL.gibSchuelerAnzahl() > kursR.gibSchuelerAnzahl()) {
				this.kursArr[i - 1] = kursR;
				this.kursArr[i] = kursL;
			}
		}
	}

	/**
	 * Debug Ausgabe. Nur für Testzwecke.
	 */
	public debug() : void {
		for (let i : number = 0; i < this.kursArr.length; i++){
			console.log(JSON.stringify("    " + this.kursArr[i] + " --> " + this.kursArr[i].gibSchuelerAnzahl() + " SuS."));
		}
	}

	/**
	 * Liefert TRUE, falls mindestens ein Kurs dieser Fachart ein Multikur ist.
	 * 
	 * @return TRUE, falls mindestens ein Kurs dieser Fachart ein Multikur ist.
	 */
	public gibHatMultikurs() : boolean {
		for (let kurs of this.kursArr) {
			if (kurs.gibSchienenAnzahl() > 1) {
				return true;
			}
		}
		return false;
	}

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

}

export function cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynFachart(obj : unknown) : KursblockungDynFachart {
	return obj as KursblockungDynFachart;
}
