import { UmbWorkspaceViewContext } from './workspace-view.context.js';
import { UMB_WORKSPACE_EDITOR_CONTEXT } from './workspace-editor.context-token.js';
import { UmbBasicState, mergeObservables } from '../../../../../libs/observable-api/index.js';
import { UmbContextBase } from '../../../../../libs/class-api/index.js';
import { UmbExtensionsManifestInitializer } from '../../../../../libs/extension-api/index.js';
import { umbExtensionsRegistry } from '../../../extension-registry/index.js';
export class UmbWorkspaceEditorContext extends UmbContextBase {
    //
    #init;
    /**
     * State holding the permitted Workspace Views as a Workspace View Context
     */
    #manifests;
    #overrides;
    // A storage and cache for the current contexts, to enable communicating to them and to avoid re-initializing them every time there is a change of manifests/overrides. [NL]
    #contexts;
    #variantId;
    constructor(host) {
        super(host, UMB_WORKSPACE_EDITOR_CONTEXT);
        /**
         * State holding the permitted Workspace Views as a Workspace View Context
         */
        this.#manifests = new UmbBasicState([]);
        this.#overrides = new UmbBasicState([]);
        this.views = mergeObservables([this.#manifests.asObservable(), this.#overrides.asObservable()], ([manifests, overrides]) => {
            let contexts = this.#contexts;
            // remove ones that are no longer contained in the workspaceViews (And thereby make the new array):
            const contextsToKeep = contexts.filter((view) => {
                const keep = manifests.some((manifest) => manifest.alias === view.manifest.alias);
                if (!keep) {
                    view.destroy();
                }
                return keep;
            });
            const hasDiff = contextsToKeep.length !== manifests.length;
            if (hasDiff) {
                contexts = [...contextsToKeep];
                // Add ones that are new:
                manifests
                    .filter((manifest) => !contextsToKeep.some((x) => x.manifest.alias === manifest.alias))
                    .forEach((manifest) => {
                    const context = new UmbWorkspaceViewContext(this, manifest);
                    context.setVariantId(this.#variantId);
                    context.setTitle(manifest.meta.label);
                    context.inherit();
                    contexts.push(context);
                });
            }
            // Apply overrides:
            contexts.forEach((context) => {
                const override = overrides.find((x) => x.alias === context.manifest.alias);
                if (override) {
                    // Test to see if there is a change, to avoid unnecessary updates, this prevents re-setting the manifest again and again. [NL]
                    const overrideKeys = Object.keys(override);
                    const hasOverrideDiff = overrideKeys.some((key) => context.manifest[key] !== override[key]);
                    if (hasOverrideDiff) {
                        context.manifest = {
                            ...context.manifest,
                            ...override,
                            meta: { ...context.manifest.meta, ...override.meta },
                        };
                    }
                }
            });
            // sort contexts to match manifests weights:
            contexts.sort((a, b) => (b.manifest.weight || 0) - (a.manifest.weight || 0));
            this.#contexts = contexts;
            return contexts;
        }, 
        // Custom memoize method, to check context instance and manifest instance:
        (previousValue, currentValue) => {
            return (previousValue === currentValue &&
                currentValue.some((x) => x.manifest === previousValue.find((y) => y.manifest.alias === x.manifest.alias)?.manifest));
        });
        // A storage and cache for the current contexts, to enable communicating to them and to avoid re-initializing them every time there is a change of manifests/overrides. [NL]
        this.#contexts = new Array();
        this.#init = new UmbExtensionsManifestInitializer(this, umbExtensionsRegistry, 'workspaceView', null, (workspaceViews) => {
            this.#manifests.setValue(workspaceViews.map((controller) => controller.manifest));
        }).asPromise();
    }
    setVariantId(variantId) {
        this.#variantId = variantId;
        this.#contexts.forEach((view) => {
            view.hints.updateScaffold({ variantId });
        });
    }
    setOverrides(overrides) {
        this.#overrides.setValue(overrides ?? []);
    }
    async getViewContext(alias) {
        await this.#init;
        return this.#contexts.find((view) => view.manifest.alias === alias);
    }
}
