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

const personalityScaleHistoryMaxsize = 10;

class PersonalityScale extends Initializing implements PersonalityScaleDefinition{

	id:string;
	start:number;
	hidden?: boolean;
	interval: number[];
	label: string | string[];
	desc?: string;
	image?: string;
	impacts:{[key:string]:number} = {};
	msg_tooHigh?: string;
	msg_tooLow?: string;
	actions?: { [key: string]: PersonalityRequirement; };
	functions?: { [key: string]: (any: any) => any; };

	#pc: PlayerCharacter;

	static get(scaleId:string,pc:PlayerCharacter):PersonalityScale{
		const newScale = new PersonalityScale(PersonalityScale.#staticData(scaleId));
		newScale.id = scaleId;
		newScale.#pc = pc;
		return newScale;
	}

	static #staticData(scaleId:string):{ [key: string]: any; }{
		return setup.personalityScales[scaleId];
	}

	get current():number{
		return this.#dataEntry.history[0][1];
	}
	set current(v:number){
		v = Math.clamp(v,this.interval[0],this.interval[1]);
		this.#dataEntry.history[0][1] = v;
	}

	get currentYesterday(){
		return this.#dataEntry.history[1][1];
	}

	get #dataEntry(){
		const daystartS = State.variables.time.daystartS;

		let dataEntry = this.#pc._personalityValues[this.id];

		if(dataEntry.history[0][0] != daystartS)
			dataEntry.history.unshift([daystartS,dataEntry.history[0][1]]);

		if(dataEntry.history.length > personalityScaleHistoryMaxsize)
			dataEntry.history.pop();

		return dataEntry;
	}

	effectOfAction(requirement:PersonalityRequirement):{willpower:number, shift:number}{
		if(typeof requirement.target == "number"){
			if(this.current < requirement.target)
				return this.effectOfAction({min:requirement.target, impact: requirement.impact});
			return this.effectOfAction({max:requirement.target, impact: requirement.impact});
		}
		
		let impact:number;
		if(typeof requirement.impact == "string")
			impact = this.impacts[requirement.impact] ?? 1;
		else
			impact = requirement.impact;

		impact ??= 1;


		let difference: number;
		let shiftDirection=0;

		if(typeof requirement.max == "number"){
			difference = this.current - requirement.max;
			if(difference <= 0)
				return {willpower:0, shift:0};
			shiftDirection = -1;
		}else if(typeof requirement.min == "number"){
			difference = requirement.min - this.current;
			if(difference <= 0)
				return {willpower:0, shift:0};	
			shiftDirection = 1;
		}
		
		const differenceWithOffset = difference + 5;

		const shift = Math.min(difference,differenceWithOffset / 100 * impact) * shiftDirection;
		const willpowerCost = Math.ceil(difference * impact /4);

		return {willpower:willpowerCost, shift:shift};
	}

	moveTo(v:number):number{
		const current = this.current;
		const diffference = v - current;
		const inreaseRaw = diffference / 10;
		const increaseEffective = Math.ceilAbs(inreaseRaw);
		this.current += increaseEffective;
		return this.current;
	}

	requiredWillpower(targetValue:number){
		/*let effecitveDifference = Math.max(0,targetValue-this.#value);
		if(effecitveDifference <= 30)
			return Math.ceil(Math.pow(2,effecitveDifference/10)*10)-10;
		return Infinity;*/
	}

	constructor(ps={}){
		super();
		this.init(ps);
	}
	
}

setup.PersonalityScale = PersonalityScale;
setup.personalityScales = {};