class Drugs{
	_drugs:{[key:string]:DrugInCharacter} = {};
	get activeEffects():{[key: string]:Effect}{
		return Object.fromEntries(this.activeEffectIds.map((effectId)=>[effectId,setup.getEffect(effectId)]));
	}

	get activeEffectIds(){
		var activeEffects = [];
		for(const [drugId,drugData] of Object.entries(this._drugs)){
			const drugSettings = setup.getDrug(drugId);
			const effects = drugSettings.effects ?? {};
			const currentVol = drugData.vol;
			let mainEffect = undefined;
			for(const [effectId,effectData] of Object.entries(effects)){
				const condition = effectData.condition;
				if('min' in condition && condition.min > currentVol)
					continue;
				if('max' in condition && condition.max <= currentVol)
					continue;
				mainEffect = effectData.effect;
				activeEffects.push(mainEffect);
				break;
			}

			const byproductEffects = drugSettings.byproduct?.effects ?? {};
			for(const [effectId,effectData] of Object.entries(byproductEffects)){
				const condition = effectData.condition;
				if('min' in condition && condition.min > currentVol)
					continue;
				if('max' in condition && condition.max <= currentVol)
					continue;
				if(condition.mainEffectsInactive && mainEffect)
					continue;
				activeEffects.push(effectData.effect);
				break;
			}
		}
		return activeEffects;
	}

	deteriorate(minutes){
		let newDrugsValue = {};
		for(const [drugId,drugData] of Object.entries(this._drugs)){
			let newDrugData:DrugInCharacter = {vol:0};
			const drugSettings = setup.getDrug(drugId);
			const deterioration = drugSettings.deterioration * minutes;
			const newVolume = Math.max(0,drugData.vol - deterioration);
			newDrugData.vol = newVolume;
			if(drugSettings.byproduct){
				const byproductDeterioration = drugSettings.byproduct.deterioration * minutes;
				const newByproduct = Math.max(0,(drugData.byproduct ?? 0) - byproductDeterioration);
				newDrugData.byproduct = newByproduct;
			}
			if(newDrugData.vol || newDrugData.byproduct)
				newDrugsValue[drugId] = newDrugData;

		}
		this._drugs = newDrugsValue;
	}

	vol(drugId){
		return this._drugs[drugId]?.vol ?? 0;
	}

	volInc(drugId, inc){
		const drugSettings = setup.getDrug(drugId);

		this._drugs[drugId] ??= {vol:0};
		this._drugs[drugId].vol += inc;

		if(drugSettings.byproduct){
			const byproductBuildup = drugSettings.byproduct.buildup ?? 1;
			this._drugs[drugId].byproduct ??= 0;
			this._drugs[drugId].byproduct += inc * byproductBuildup;
		}
	}

	volSet(drugId,v){
		if(typeof v != "number" || isNaN(v)){
			console.error("Trying to set drug to non-number",drugId,v);
			return;
		}
		this._drugs[drugId] ??= {vol:0};
		const difference = v - this._drugs[drugId].vol;
		if(difference > 0)
			this.volInc(drugId,difference);
		else
			this._drugs[drugId].vol = v;
	}

	constructor(drugs={}){this._drugs=drugs}

	_init(data){
		Object.keys(data).forEach(function (pn) {
			this[pn] = clone(data[pn]);
		}, this);

		return this;
	}

	clone = function () {
		return (new setup.Drugs())._init(this);
	};

	toJSON = function () {
		var ownData = {};
		Object.keys(this).forEach(function (data) {
			if(typeof this[data] !== "function")
				ownData[data] = clone(this[data]);
		}, this);
		return JSON.reviveWrapper('(new setup.Drugs())._init($ReviveData$)', ownData);
	};
}

setup.Drugs = Drugs;