import { defineWorkbookFeaturePlugin, } from '@bilig/workbook/features';
export class WorkbookFeatureRegistry {
    plugins = new Map();
    activeFeatureIds = [];
    disposed = false;
    register(plugin) {
        this.assertNotDisposed();
        const normalized = defineWorkbookFeaturePlugin(plugin);
        if (this.plugins.has(normalized.id)) {
            throw new Error(`Workbook feature ${normalized.id} is already registered`);
        }
        this.plugins.set(normalized.id, normalized);
        normalized.register?.(this.lifecycleContext(normalized.id));
        return normalized;
    }
    activateAll() {
        this.assertNotDisposed();
        const visiting = new Set();
        const visited = new Set(this.activeFeatureIds);
        for (const featureId of this.plugins.keys()) {
            this.activateFeature(featureId, visiting, visited);
        }
        return this.listActiveFeatureIds();
    }
    disposeAll() {
        if (this.disposed) {
            return;
        }
        for (const featureId of this.activeFeatureIds.toReversed()) {
            this.plugins.get(featureId)?.dispose?.(this.lifecycleContext(featureId));
        }
        this.activeFeatureIds.length = 0;
        this.plugins.clear();
        this.disposed = true;
    }
    get(featureId) {
        return this.plugins.get(featureId);
    }
    listPlugins() {
        return [...this.plugins.values()];
    }
    listActiveFeatureIds() {
        return Object.freeze([...this.activeFeatureIds]);
    }
    listCommandDescriptors() {
        const descriptors = [];
        this.listPlugins().forEach((plugin) => {
            descriptors.push(...plugin.commands);
        });
        return descriptors;
    }
    listProjectionInterceptors() {
        const interceptors = [];
        this.listPlugins().forEach((plugin) => {
            interceptors.push(...plugin.projectionInterceptors);
        });
        return interceptors;
    }
    listUiContributions() {
        const contributions = [];
        this.listPlugins().forEach((plugin) => {
            contributions.push(...plugin.uiContributions);
        });
        return contributions.toSorted((left, right) => {
            const orderDelta = (left.order ?? 0) - (right.order ?? 0);
            return orderDelta === 0 ? left.id.localeCompare(right.id) : orderDelta;
        });
    }
    activateFeature(featureId, visiting, visited) {
        if (visited.has(featureId)) {
            return;
        }
        const plugin = this.plugins.get(featureId);
        if (!plugin) {
            throw new Error(`Workbook feature ${featureId} is not registered`);
        }
        if (visiting.has(featureId)) {
            throw new Error(`Workbook feature dependency cycle includes ${featureId}`);
        }
        visiting.add(featureId);
        for (const dependency of plugin.dependsOn ?? []) {
            if (!this.plugins.has(dependency)) {
                throw new Error(`Workbook feature ${plugin.id} depends on missing feature ${dependency}`);
            }
            this.activateFeature(dependency, visiting, visited);
        }
        visiting.delete(featureId);
        plugin.activate?.(this.lifecycleContext(featureId));
        this.activeFeatureIds.push(featureId);
        visited.add(featureId);
    }
    lifecycleContext(featureId) {
        return {
            featureId,
            activeFeatures: this.listActiveFeatureIds(),
        };
    }
    assertNotDisposed() {
        if (this.disposed) {
            throw new Error('Workbook feature registry has been disposed');
        }
    }
}
//# sourceMappingURL=workbook-feature-registry.js.map