import { JavaObject, cast_java_lang_Object } from '../../../java/lang/JavaObject';
import { JavaInteger, cast_java_lang_Integer } from '../../../java/lang/JavaInteger';
import { NullPointerException, cast_java_lang_NullPointerException } from '../../../java/lang/NullPointerException';
import { KursblockungInputRegel, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputRegel } from '../../../core/data/kursblockung/KursblockungInputRegel';
import { JavaLong, cast_java_lang_Long } from '../../../java/lang/JavaLong';
import { GostBlockungRegel, cast_de_nrw_schule_svws_core_data_gost_GostBlockungRegel } from '../../../core/data/gost/GostBlockungRegel';
import { IllegalArgumentException, cast_java_lang_IllegalArgumentException } from '../../../java/lang/IllegalArgumentException';

export class GostKursblockungRegelTyp extends JavaObject {

	/** the name of the enumeration value */
	private readonly __name : String;

	/** the ordinal value for the enumeration value */
	private readonly __ordinal : number;

	/** an array containing all values of this enumeration */
	private static readonly all_values_by_ordinal : Array<GostKursblockungRegelTyp> = [];

	/** an array containing all values of this enumeration indexed by their name*/
	private static readonly all_values_by_name : Map<String, GostKursblockungRegelTyp> = new Map<String, GostKursblockungRegelTyp>();

	public static readonly UNDEFINIERT : GostKursblockungRegelTyp = new GostKursblockungRegelTyp("UNDEFINIERT", 0, 0);

	public static readonly SPERRE_SCHIENEN_VON_BIS : GostKursblockungRegelTyp = new GostKursblockungRegelTyp("SPERRE_SCHIENEN_VON_BIS", 1, 1);

	public static readonly FIXIERE_KURS : GostKursblockungRegelTyp = new GostKursblockungRegelTyp("FIXIERE_KURS", 2, 2);

	public static readonly SPERRE_SCHIENE_FUER_KURS : GostKursblockungRegelTyp = new GostKursblockungRegelTyp("SPERRE_SCHIENE_FUER_KURS", 3, 3);

	public readonly id : number;

	private readonly paramCount : number;

	/**
	 * Erstellt einen neuen Regel-Typ mit der angegeben ID.
	 *  
	 * @param id   die ID des Regel-Typs
	 */
	private constructor(name : string, ordinal : number, id : number) {
		super();
		this.__name = name;
		this.__ordinal = ordinal;
		GostKursblockungRegelTyp.all_values_by_ordinal.push(this);
		GostKursblockungRegelTyp.all_values_by_name.set(name, this);
		this.id = id;
		switch (id) {
			case 0: 
				this.paramCount = 0;
				break;
			case 1: 
				this.paramCount = 3;
				break;
			case 2:
			case 3: 
				this.paramCount = 2;
				break;
			default: 
				throw new IllegalArgumentException()
		}
	}

	/**
	 * Ermittelt den Regel-Typ anhand seiner ID und gibt diesen zurück.
	 *
	 * @param id   die ID des Regel-Typs
	 * 
	 * @return der Regel-Typ
	 */
	public static fromID(id : Number | null) : GostKursblockungRegelTyp {
		if ((id === null) || (id < 0)) 
			return GostKursblockungRegelTyp.UNDEFINIERT;
		let values : Array<GostKursblockungRegelTyp> = GostKursblockungRegelTyp.values();
		if (id > values.length) 
			return GostKursblockungRegelTyp.UNDEFINIERT;
		return values[id.valueOf()];
	}

	/**
	 * Gibt die Anzahl der Parameter für diesen Regel-Type zurück.
	 * 
	 * @return die Anzahl der Parameter für diesen Regel-Type zurück.
	 */
	public getParamCount() : number {
		return this.paramCount;
	}

	/**
	 * Erstellt ein neues Regel-Objekt der Klasse {@link KursblockungInputRegel} mithilfe der angegebenen
	 * Parameter.
	 *  
	 * @param params   die Parameter für das Regel-Objekt
	 * 
	 * @return das Regel-Objekt
	 * 
	 * @throws IllegalArgumentException   wenn die Anzahl der Parameter nicht zu diesem Regel-Typ passt
	 */
	public create(...params : Array<Number>) : KursblockungInputRegel {
		if ((params === null) || (params.length !== this.paramCount)) 
			throw new IllegalArgumentException()
		let regel : KursblockungInputRegel = new KursblockungInputRegel();
		regel.id = this.id;
		regel.daten = Array(params.length).fill(null);
		for (let i : number = 0; i < params.length; i++){
			let data : Number | null = params[i];
			if (data === null) 
				throw new NullPointerException()
			regel.daten[i] = data;
		}
		return regel;
	}

	/**
	 * Erstellt ein neues Regel-Objekt der Klasse {@link KursblockungInputRegel} mithilfe der angegebenen
	 * ID und der angegebenen Parameter.
	 * 
	 * @param id       die ID des Regel-Typs
	 * @param params   die Parameter der zu erstellenden Regel
	 * 
	 * @return das Regel-Objekt
	 * 
	 * @throws IllegalArgumentException   wenn es keine gültige Regel für angegeben ID gibt oder die Anzahl 
	 *                                    der Parameter nicht zu dem Regel-Typ passt
	 */
	public static createByID(id : Number | null, ...params : Array<Number>) : KursblockungInputRegel {
		let typ : GostKursblockungRegelTyp = GostKursblockungRegelTyp.fromID(id);
		if (JavaObject.equalsTranspiler(typ, (GostKursblockungRegelTyp.UNDEFINIERT))) 
			throw new IllegalArgumentException("Ungültiger Regel-Typ")
		return typ.create(...params);
	}

	/**
	 * Erstellt ein neues Regel-Objekt der Klasse {@link KursblockungInputRegel} mithilfe der angegebenen
	 * Regel.
	 * 
	 * @param regel       die Regel als Core-DTO
	 * 
	 * @return das Regel-Objekt
	 * 
	 * @throws IllegalArgumentException   wenn es keine gültige Regel für angegeben ID gibt oder die Anzahl 
	 *                                    der Parameter nicht zu dem Regel-Typ passt
	 */
	public static createFrom(regel : GostBlockungRegel) : KursblockungInputRegel {
		return GostKursblockungRegelTyp.createByID(regel.typ, ...regel.parameter.toArray(Array(0).fill(null)));
	}

	/**
	 * Returns the name of this enumeration value.
	 *
	 * @returns the name
	 */
	private name() : String {
		return this.__name;
	}

	/**
	 * Returns the ordinal value of this enumeration value.
	 *
	 * @returns the ordinal value
	 */
	private ordinal() : number {
		return this.__ordinal;
	}

	/**
	 * Returns the name of this enumeration value.
	 *
	 * @returns the name
	 */
	public toString() : String {
		return this.__name;
	}

	/**
	 * Returns true if this and the other enumeration values are equal.
	 *
	 * @param other   the other enumeration value
	 *
	 * @returns true if they are equal and false otherwise
	 */
	public equals(other : JavaObject) : boolean {
		if (!(other instanceof GostKursblockungRegelTyp))
			return false;
		return this === other;
	}

	/**
	 * Returns the ordinal value as hashcode, since the ordinal value is unique.
	 *
	 * @returns the ordinal value as hashcode
	 */
	public hashCode() : number {
		return this.__ordinal;
	}

	/**
	 * Compares this enumeration value with the other enumeration value by their ordinal value.
	 *
	 * @param other   the other enumeration value
	 *
	 * @returns a negative, zero or postive value as this enumeration value is less than, equal to
	 *          or greater than the other enumeration value
	 */
	public compareTo(other : GostKursblockungRegelTyp) : number {
		return this.__ordinal - other.__ordinal;
	}

	/**
	 * Returns an array with enumeration values.
	 *
	 * @returns the array with enumeration values
	 */
	public static values() : Array<GostKursblockungRegelTyp> {
		return [...this.all_values_by_ordinal];
	}

	/**
	 * Returns the enumeration value with the specified name.
	 *
	 * @param name   the name of the enumeration value
	 *
	 * @returns the enumeration values or null
	 */
	public static valueOf(name : String) : GostKursblockungRegelTyp | null {
		let tmp : GostKursblockungRegelTyp | undefined = this.all_values_by_name.get(name);
		return (!tmp) ? null : tmp;
	}

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

}

export function cast_de_nrw_schule_svws_core_types_kursblockung_GostKursblockungRegelTyp(obj : unknown) : GostKursblockungRegelTyp {
	return obj as GostKursblockungRegelTyp;
}
