import { Plugin } from './plugin.js';
import { MetaModule } from '../meta-api/module.js';
export class ToolboxEntry {
    constructor(toolbox, entry) {
        this.toolbox = toolbox;
        this.entry = entry;
    }
    dispose() {
        this.toolbox.removeEntry(this.entry);
    }
    update(entry) {
        this.toolbox.updateEntry(this.entry, entry);
        this.entry = entry;
    }
}
export class Toolbox extends Plugin {
    constructor() {
        super(...arguments);
        this.entries = [];
        this._entries = [];
        this.whitelist = null;
        this.installedEntries = new Set();
    }
    onInstall(editor) {
        this.editor = editor;
        this.renderer = this.editor.sourceEditor.getApiRenderer();
    }
    setEntries(entries) {
        this.entries = entries;
    }
    /**
     * Runs the onInstall function of the entry if available.
     * Will avoid running the onInstall more than once for the current toolbox
     * @param entry A toolbox entry
     */
    installEntry(entry) {
        if (!this.editor || this.installedEntries.has(entry)) {
            return;
        }
        let realEntry = entry;
        if (typeof entry === 'function') {
            realEntry = entry(this.editor);
        }
        const mod = this.editor.output.runner.getModule(realEntry.id || realEntry.name);
        if (typeof realEntry.onInstall === 'function') {
            realEntry.onInstall(this.editor, mod);
        }
        this._entries.push(realEntry);
        this.installedEntries.add(entry);
    }
    addEntry(entry, position) {
        if (!this.editor) {
            throw new Error('Could not add entry: The editor was not defined');
        }
        const injectIndex = typeof position === 'undefined' ? this.entries.length : position;
        const disposableEntry = new ToolboxEntry(this, entry);
        this.entries.splice(injectIndex, 0, entry);
        this.update();
        return disposableEntry;
    }
    removeEntry(entry) {
        const index = this._entries.indexOf(entry);
        this._entries.splice(index, 1);
        this.update();
    }
    updateEntry(oldEntry, entry) {
        const index = this.entries.indexOf(oldEntry);
        this.entries.splice(index, 1, entry);
        this.update();
    }
    setWhitelist(whitelist) {
        this.whitelist = whitelist;
        this.update();
    }
    whitelistEntry(id, whitelist) {
        this.whitelist = this.whitelist || {};
        this.whitelist[id] = whitelist;
        this.update();
    }
    removeWhitelistEntry(id) {
        if (!this.whitelist || !this.whitelist[id]) {
            return;
        }
        delete this.whitelist[id];
        this.update();
    }
    update() {
        // Not injected yet, let the inject callback generate the toolbox
        if (!this.editor || !this.editor.injected) {
            return;
        }
        this.onInject();
    }
    onInject() {
        if (!this.editor || !this.renderer) {
            return;
        }
        this.entries.forEach((entry) => {
            this.installEntry(entry);
        });
        let entries = this._entries;
        if (this.whitelist) {
            const modules = Object.keys(this.whitelist);
            entries = entries.filter(e => modules.indexOf(e.name) !== -1);
        }
        const toolbox = entries
            .map(entry => {
            let moduleWhitelist = null;
            if (this.whitelist && this.whitelist[entry.name]) {
                moduleWhitelist = this.whitelist[entry.name];
            }
            return this.renderer.renderToolboxEntry(new MetaModule(entry, undefined), moduleWhitelist);
        })
            .filter(entry => entry);
        this.editor.sourceEditor.setToolbox(toolbox);
    }
    registerQueryHandlers(engine) {
    }
}
export default Toolbox;
//# sourceMappingURL=toolbox.js.map