"use strict";
/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module UiProvider
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.UiItemsManager = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const UiFramework_1 = require("../UiFramework");
const AbstractUiItemsManager_1 = require("./AbstractUiItemsManager");
/** Controls registering of UiItemsProviders and calls the provider's methods when populating different parts of the User Interface.
 * @public
 */
class UiItemsManager {
    /** For use in unit testing
     * @internal */
    static clearAllProviders() {
        if (this._abstractAdapter)
            return this._abstractAdapter.clearAllProviders();
        UiItemsManager._registeredUiItemsProviders.clear();
    }
    /** Event raised any time a UiProvider is registered or unregistered. */
    static get onUiProviderRegisteredEvent() {
        if (this._abstractAdapter)
            return this._abstractAdapter.onUiProviderRegisteredEvent;
        return this._onUiProviderRegisteredEvent;
    }
    /** Return number of registered UiProvider. */
    static get registeredProviderIds() {
        if (this._abstractAdapter)
            return this._abstractAdapter.registeredProviderIds;
        const ids = [...UiItemsManager._registeredUiItemsProviders.keys()];
        return ids;
    }
    /** Return true if there is any registered UiProvider. */
    static get hasRegisteredProviders() {
        if (this._abstractAdapter)
            return this._abstractAdapter.hasRegisteredProviders;
        return this._registeredUiItemsProviders.size > 0;
    }
    /**
     * Retrieves a previously loaded UiItemsProvider.
     * @param providerId id of the UiItemsProvider to get
     */
    static getUiItemsProvider(providerId) {
        if (this._abstractAdapter)
            return this._abstractAdapter.getUiItemsProvider(providerId);
        return UiItemsManager._registeredUiItemsProviders.get(providerId)?.provider;
    }
    static sendRegisteredEvent(args) {
        UiItemsManager.onUiProviderRegisteredEvent.raiseEvent(args);
    }
    /**
     * Registers a UiItemsProvider with the UiItemsManager.
     * @param uiProvider the UI items provider to register.
     */
    static register(uiProvider, overrides) {
        if (this._abstractAdapter)
            return this._abstractAdapter.register(uiProvider, overrides);
        const providerId = overrides?.providerId ?? uiProvider.id;
        if (UiItemsManager.getUiItemsProvider(providerId)) {
            core_bentley_1.Logger.logInfo(UiFramework_1.UiFramework.loggerCategory(this), `UiItemsProvider (${providerId}) is already loaded`);
        }
        else {
            UiItemsManager._registeredUiItemsProviders.set(providerId, {
                provider: uiProvider,
                overrides,
            });
            core_bentley_1.Logger.logInfo(UiFramework_1.UiFramework.loggerCategory(this), `UiItemsProvider ${uiProvider.id} registered as ${providerId} `);
            UiItemsManager.sendRegisteredEvent({ providerId });
        }
    }
    /** Remove a specific UiItemsProvider from the list of available providers. */
    static unregister(providerId) {
        if (this._abstractAdapter)
            return this._abstractAdapter.unregister(providerId);
        const provider = UiItemsManager.getUiItemsProvider(providerId);
        if (!provider)
            return;
        provider.onUnregister && provider.onUnregister();
        UiItemsManager._registeredUiItemsProviders.delete(providerId);
        core_bentley_1.Logger.logInfo(UiFramework_1.UiFramework.loggerCategory(this), `UiItemsProvider (${providerId}) unloaded`);
        // trigger a refresh of the ui
        UiItemsManager.sendRegisteredEvent({ providerId });
    }
    static allowItemsFromProvider(entry, stageId, stageUsage) {
        // istanbul ignore else
        const overrides = entry.overrides;
        if (undefined !== stageId &&
            overrides?.stageIds &&
            !overrides.stageIds.some((value) => value === stageId))
            return false;
        if (undefined !== stageUsage &&
            overrides?.stageUsages &&
            !overrides.stageUsages.some((value) => value === stageUsage))
            return false;
        return true;
    }
    /** Called when the application is populating a toolbar so that any registered UiItemsProvider can add tool buttons that either either execute
     * an action or specify a registered ToolId into toolbar.
     * @param stageId a string identifier the active stage.
     * @param stageUsage the StageUsage of the active stage.
     * @param usage usage of the toolbar
     * @param orientation orientation of the toolbar
     * @returns an array of error messages. The array will be empty if the load is successful, otherwise it is a list of one or more problems.
     */
    static getToolbarButtonItems(stageId, stageUsage, usage, orientation) {
        if (this._abstractAdapter)
            return this._abstractAdapter.getToolbarButtonItems(stageId, stageUsage, usage, orientation);
        const buttonItems = [];
        UiItemsManager._registeredUiItemsProviders.forEach((entry) => {
            const uiProvider = entry.provider;
            const providerId = entry.overrides?.providerId ?? uiProvider.id;
            // istanbul ignore else
            if (uiProvider.provideToolbarItems &&
                this.allowItemsFromProvider(entry, stageId, stageUsage)) {
                uiProvider
                    .provideToolbarItems(stageId, stageUsage, usage, orientation)
                    .forEach((spec) => {
                    // ignore duplicate ids
                    if (-1 ===
                        buttonItems.findIndex((existingItem) => spec.id === existingItem.id))
                        buttonItems.push({ ...spec, providerId });
                });
            }
        });
        return buttonItems;
    }
    /** Called when the application is populating the statusbar so that any registered UiItemsProvider can add status fields
     * @param stageId a string identifier the active stage.
     * @param stageUsage the StageUsage of the active stage.
     * @returns An array of CommonStatusBarItem that will be used to create controls for the status bar.
     */
    static getStatusBarItems(stageId, stageUsage) {
        if (this._abstractAdapter)
            return this._abstractAdapter.getStatusBarItems(stageId, stageUsage);
        const statusBarItems = [];
        UiItemsManager._registeredUiItemsProviders.forEach((entry) => {
            const uiProvider = entry.provider;
            const providerId = entry.overrides?.providerId ?? uiProvider.id;
            // istanbul ignore else
            if (uiProvider.provideStatusBarItems &&
                this.allowItemsFromProvider(entry, stageId, stageUsage)) {
                uiProvider
                    .provideStatusBarItems(stageId, stageUsage)
                    .forEach((item) => {
                    // ignore duplicate ids
                    if (-1 ===
                        statusBarItems.findIndex((existingItem) => item.id === existingItem.id))
                        statusBarItems.push({ ...item, providerId });
                });
            }
        });
        return statusBarItems;
    }
    /** Called when the application is populating the statusbar so that any registered UiItemsProvider can add status fields
     * @returns An array of BackstageItem that will be used to create controls for the backstage menu.
     */
    static getBackstageItems() {
        if (this._abstractAdapter)
            return this._abstractAdapter.getBackstageItems();
        const backstageItems = [];
        UiItemsManager._registeredUiItemsProviders.forEach((entry) => {
            const uiProvider = entry.provider;
            const providerId = entry.overrides?.providerId ?? uiProvider.id;
            // istanbul ignore else
            if (uiProvider.provideBackstageItems) {
                // Note: We do not call this.allowItemsFromProvider here as backstage items
                uiProvider
                    .provideBackstageItems() //       should not be considered stage specific. If they need to be hidden
                    .forEach((item) => {
                    //       the isHidden property should be set to a ConditionalBooleanValue
                    // ignore duplicate ids
                    if (-1 ===
                        backstageItems.findIndex((existingItem) => item.id === existingItem.id))
                        backstageItems.push({ ...item, providerId });
                });
            }
        });
        return backstageItems;
    }
    /** Called when the application is populating the Stage Panels so that any registered UiItemsProvider can add widgets
     * @param stageId a string identifier the active stage.
     * @param stageUsage the StageUsage of the active stage.
     * @param location the location within the stage.
     * @param section the section within location.
     * @returns An array of widgets.
     */
    static getWidgets(stageId, stageUsage, location, section) {
        if (this._abstractAdapter)
            return this._abstractAdapter.getWidgets(stageId, stageUsage, location, section);
        const widgets = [];
        UiItemsManager._registeredUiItemsProviders.forEach((entry) => {
            const uiProvider = entry.provider;
            const providerId = entry.overrides?.providerId ?? uiProvider.id;
            // istanbul ignore else
            if (uiProvider.provideWidgets &&
                this.allowItemsFromProvider(entry, stageId, stageUsage)) {
                uiProvider
                    .provideWidgets(stageId, stageUsage, location, section)
                    .forEach((widget) => {
                    // ignore duplicate ids
                    if (-1 ===
                        widgets.findIndex((existingItem) => widget.id === existingItem.id))
                        widgets.push({ ...widget, providerId });
                });
            }
        });
        return widgets;
    }
}
UiItemsManager._registeredUiItemsProviders = new Map();
UiItemsManager._onUiProviderRegisteredEvent = new core_bentley_1.BeUiEvent();
UiItemsManager._abstractAdapter = (0, AbstractUiItemsManager_1.createAbstractUiItemsManagerAdapter)();
exports.UiItemsManager = UiItemsManager;
//# sourceMappingURL=UiItemsManager.js.map