class QuestsDict{

	_quests = {};

	quest(questId){
		if(!this._quests[questId])
			this._quests[questId] = new setup.Quest(questId);
		return new Proxy(this._quests[questId],setup.Quest.handler);
	}

	activeQuests(){
		let result = {};
		for (const [key, value] of Object.entries(this._quests)) {
			if(typeof value === "function")
				continue;
			if(this.questIsActive(key)){
				result[key] = value;
			}
		}
		return result;
	}

	failedQuests(){
		let result = {};
		for (const [key, value] of Object.entries(this._quests)) {
			if(typeof value === "function")
				continue;
			if(this.questIsFailed(key)){
				result[key] = value;
			}
		}
		return result;
	}

	eventExecute(questId,eventId){
		if(!this._quests[questId]){
			console.error('Called event of non-existing quest:',questId,eventId);
			return;
		}
		if(!this.questIsActive(questId))
			console.warn('Called event of deactivated quest:',questId,eventId);
		this._quests[questId].eventExecute(eventId);
	}

	/**
	 * Gets a value from an active quest. Returns default if the quest is not active.
	 * @date 6/14/2023 - 1:34:31 PM
	 *
	 * @param {string} questId
	 * @param {string} field
	 * @param {*} def
	 */
	get(questId,field,def=undefined){
		if(!this.questIsActive(questId))
			return def;
		return this._quests[questId].get(field,def);
	}

	active(questId){return this.questIsActive(questId);}
	questIsActive(questId){
		if(!this._quests[questId])
			return false;
		return (this._quests[questId].state === 1);
	}

	failed(questId){return this.questIsFailed(questId);}
	questIsFailed(questId){
		if(!this._quests[questId])
			return false;
		return (this._quests[questId].state < 0);
	}

	started(questId){return this.questIsStarted(questId);}
	questIsStarted(questId){
		if(!this._quests[questId])
			return false;
		return (this._quests[questId].state !== 0);
	}

	start(questId,restart=false){this.questStart(questId,restart)}
	questStart(questId,restart=false){
		if(!this._quests[questId] || restart){
			this._quests[questId] = new setup.Quest();
			this._quests[questId].id = questId;
			this._quests[questId].start();
		} else {
			return; //The quest is started and is not set to restart.
		}

	}


	constructor(){}

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

		return this;
	}

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

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

setup.QuestsDict = QuestsDict;