/// <reference path="../../../_system/_shared/Initializing.ts"/>
/// <reference path="AppearanceFunctions.ts" />


class AppearanceModificator extends Initializing{
	static get(modificatorId:string){
		let staticData = setup.appearanceModificators[modificatorId];
		if(!staticData)
			return AppearanceModificator.null;
		return new AppearanceModificator().init(staticData);
	}

	static get null(){return NullAppearanceModificator.INSTANCE;}

	get isActive():boolean{return true;}
}

class NullAppearanceModificator extends AppearanceModificator{
	private static _instance = new NullAppearanceModificator();
	static get INSTANCE(){return this._instance;}

	get isActive():boolean{return false;}
}

class Appearance{

    private pc: PlayerCharacter

	static get(playerCharacter: PlayerCharacter){
		return new Appearance(playerCharacter);
	}

    constructor(playerCharacter: PlayerCharacter){
        this.pc = playerCharacter;
    }

	modifiers(includeGenetic:boolean,includeLasting:boolean,includeCurrent:boolean):Array<AppearanceModificator>{
		let result = [];
		if(includeGenetic)
			result = result.concat(this.geneticModifiers);
		if(includeLasting)
			result = result.concat(this.lastingModifiers);
		if(includeCurrent)
			result = result.concat(this.currentModifiers);
		return result;
	}

	modifiersFromFunctions(type:'current'|'lasting'|'genetic'):AppearanceModificator[]{
		let result:AppearanceModificator[]=[];
		for(const func of Object.values(setup.appearanceFunctions[type])){
			const id = func(this.pc);
			if(id)
				result.push(AppearanceModificator.get(id));
		}
		return result;
	}

	//#region Current
		get currentValue(){
			return this.modifiers(true,true,true).fancyMathEvaluate();
		}

		get currentModifiers():Array<AppearanceModificator>{
			return [
				this.clothesModificator,
				this.hairBrushModificator,
				this.leghairModificator,
				this.makeupModificator,
				...this.modifiersFromFunctions('current')
			].filter(modificator=>modificator.isActive);
		}

		get clothesModificator():AppearanceModificator{
			const wardrobe = State.variables.wardrobe;
			if(wardrobe.clothes.isValidItem)
				return AppearanceModificator.get(`clothes_q_${wardrobe.clothes.quality}`);
			return AppearanceModificator.null;
		}

		get hairBrushModificator():AppearanceModificator{
			if(this.pc.pcs_hairbsh == 0)
				return AppearanceModificator.get(`hair_notBrushed`);
			return AppearanceModificator.null;
		}

		get leghairModificator():AppearanceModificator{
			return AppearanceModificator.get(`legHair_${this.pc.legHairVisibility}`);
		}

		get makeupModificator():AppearanceModificator{
			let makeupAmount = this.pc.makeupAmount;
			if(makeupAmount > 0){
				let makeupQuality = this.pc.makeupQuality;
				if(makeupQuality >= 0)
					return AppearanceModificator.get(`makeup_${makeupAmount}_${makeupQuality}`);
				else
					return AppearanceModificator.get(`makeup_${makeupAmount}_m${makeupQuality*-1}`);
			}
			return AppearanceModificator.null;
		}

				

	//#endregion

	//#region Genetic
		get geneticValue(){
			return this.modifiers(true,false,false).fancyMathEvaluate();
		}

		get geneticModifiers():Array<AppearanceModificator>{
			return [
				this.faceModificator,
				this.heightModificator,
				this.titsModificator,
				...this.modifiersFromFunctions('genetic')
			].filter(modificator=>modificator.isActive);
		}
		

		get faceModificator():AppearanceModificator{
			switch(this.pc.faceAttractiveness){
				case -3: return AppearanceModificator.get('base_m3');
				case -2: return AppearanceModificator.get('base_m2');
				case -1: return AppearanceModificator.get('base_m1');
				case 0: return AppearanceModificator.get('base_0');
				case 1: return AppearanceModificator.get('base_1');
				case 2: return AppearanceModificator.get('base_2');
				case 3: return AppearanceModificator.get('base_3');
			}
			return AppearanceModificator.null;
		}

		get heightModificator():AppearanceModificator{
			if(this.pc.height < 150)
				return AppearanceModificator.get('height_height_150m');
			if(this.pc.height < 160)
				return AppearanceModificator.get('height_height_150_160');
			if(this.pc.height < 170)
				return AppearanceModificator.get('height_height_160_170');
			if(this.pc.height < 180)
				return AppearanceModificator.get('height_height_170_180');
			if(this.pc.height < 190)
				return AppearanceModificator.get('height_height_180_190');
			return AppearanceModificator.get('height_height_190p');
		}

		get titsModificator():AppearanceModificator{
			return AppearanceModificator.get(`tits_${this.pc.tits}`);
		}

				
	//#endregion

	//#region Lasting
		get lastingValue(){
			return this.modifiers(true,true,false).fancyMathEvaluate();
		}

		get lastingModifiers():Array<AppearanceModificator>{
			return [
				this.bmiModificator,
				this.skinModificator,
				this.teethModificator,
				...this.modifiersFromFunctions('lasting')
			].filter(modificator=>modificator.isActive);
		}

		get bmiModificator():AppearanceModificator{
			if(this.pc.bmi < 16)
				return AppearanceModificator.get('bmi_0to16');
			if(this.pc.bmi < 17)
				return AppearanceModificator.get('bmi_16to17');
			if(this.pc.bmi < 18.5)
				return AppearanceModificator.get('bmi_17to185');
			if(this.pc.bmi < 20)
				return AppearanceModificator.get('bmi_185to20');
			if(this.pc.bmi < 22)
				return AppearanceModificator.get('bmi_20to22');
			if(this.pc.bmi < 25)
				return AppearanceModificator.get('bmi_22to25');
			if(this.pc.bmi < 27)
				return AppearanceModificator.get('bmi_25to27');
			if(this.pc.bmi < 29)
				return AppearanceModificator.get('bmi_27to29');
			if(this.pc.bmi < 32)
				return AppearanceModificator.get('bmi_29to32');
			return AppearanceModificator.get('bmi_32to100');
		}
		
		get skinModificator(){
			if(this.pc.skinAppearance >= 0)
				return AppearanceModificator.get(`skin_${this.pc.skinAppearance}`);
			return AppearanceModificator.get(`skin_m${this.pc.skinAppearance}`);
		}

		get teethModificator(){
			return AppearanceModificator.get(`teeth_${this.pc.teethQuality}`);
		}
	//#endregion

}

setup.Appearance = Appearance;