export default class ModuleLoader {

    constructor({ eventBus, store, api }) {

        this.eventBus = eventBus;
        this.store = store;
        this.api = api;

        this.loadedModules = new Map();
        this.registry = new Map();

    }

    /* -------------------------------------------------------
       REGISTER STATIC MODULE
    ------------------------------------------------------- */

    register(name, moduleClass) {

        this.registry.set(name, moduleClass);

    }

    /* -------------------------------------------------------
       LOAD MODULE (lazy)
    ------------------------------------------------------- */

    async load(name, context) {

        if (this.loadedModules.has(name)) {
            return this.loadedModules.get(name);
        }

        let ModuleClass;

        if (this.registry.has(name)) {

            ModuleClass = this.registry.get(name);

        } else {

            // Dynamic import (lazy load)
            const module = await import(
                `../modules/${name}/${name}Module.js`
            );

            ModuleClass = module.default;

        }

        const instance = new ModuleClass({
            eventBus: this.eventBus,
            store: this.store,
            api: this.api,
            context
        });

        await instance.init();

        this.loadedModules.set(name, instance);

        this.eventBus.emit('module:loaded', name);

        return instance;

    }

    /* -------------------------------------------------------
       UNLOAD MODULE
    ------------------------------------------------------- */

    unload(name) {

        if (!this.loadedModules.has(name)) return;

        const module = this.loadedModules.get(name);

        if (module.destroy) {
            module.destroy();
        }

        this.loadedModules.delete(name);

        this.eventBus.emit('module:unloaded', name);

    }

    get(name) {
        return this.loadedModules.get(name) || null;
    }

}
