'use strict';
const EventManager = require('./EventManager');
const Effect = require('./Effect');
/** @typedef {{config: Object<string,*>, listeners: Object<String,function (...*)>}} */
var EffectConfig;
/**
* @property {Map} effects
*/
class EffectFactory {
constructor() {
this.effects = new Map();
}
/**
* @param {string} id
* @param {EffectConfig} config
* @param {GameState} state
*/
add(id, config, state) {
if (this.effects.has(id)) {
return;
}
let definition = Object.assign({}, config);
delete definition.listeners;
let listeners = config.listeners || {};
if (typeof listeners === 'function') {
listeners = listeners(state);
}
const eventManager = new EventManager();
for (const event in listeners) {
eventManager.add(event, listeners[event]);
}
this.effects.set(id, { definition, eventManager });
}
has(id) {
return this.effects.has(id);
}
/**
* Get a effect definition. Use `create` if you want an instance of a effect
* @param {string} id
* @return {object}
*/
get(id) {
return this.get(id);
}
/**
* @param {string} id effect id
* @param {?object} config Effect.config override
* @param {?object} state Effect.state override
* @return {Effect}
*/
create(id, config = {}, state = {}) {
const entry = this.effects.get(id);
if (!entry || !entry.definition) {
throw new Error(`No valid entry definition found for effect ${id}.`);
}
let def = Object.assign({}, entry.definition);
def.config = Object.assign(def.config, config);
def.state = Object.assign(def.state || {}, state);
const effect = new Effect(id, def);
entry.eventManager.attach(effect);
return effect;
}
}
module.exports = EffectFactory;