/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/* eslint-disable deprecation/deprecation */
/** @packageDocumentation
 * @module Widget
 */
import { BeUiEvent, Logger } from "@itwin/core-bentley";
import { AbstractZoneLocation, StagePanelLocation, StagePanelSection, UiItemsManager } from "@itwin/appui-abstract";
import { UiFramework } from "../UiFramework";
import { getStableWidgetProps, ZoneLocation } from "../zones/Zone";
import { WidgetDef } from "./WidgetDef";
import { createStableWidgetDef } from "./StableWidgetDef";
/** Event class for [[this.onWidgetsChanged]].
 * @internal
 */
export class WidgetsChangedEvent extends BeUiEvent {
}
function isZoneLocation(location) {
    return location >= ZoneLocation.TopLeft && location <= ZoneLocation.BottomRight;
}
function getLocationName(location) {
    return isZoneLocation(location) ? ZoneLocation[location] : StagePanelLocation[location];
}
function getWidgetManagerStableWidgetId(stageUsage, location, section, index) {
    return `uifw-wm-${stageUsage || ""}-${getLocationName(location)}-${StagePanelSection[section]}-${index}`;
}
function getAddonStableWidgetId(stageUsage, location, section, index) {
    return `uifw-addon-${stageUsage}-${StagePanelLocation[location]}-${StagePanelSection[section]}-${index}`;
}
/** Widget Manager class.
 * @beta
 */
export class WidgetManager {
    constructor() {
        this._widgets = [];
        /** Event raised when Widgets are changed.
         * @internal
         */
        this.onWidgetsChanged = new WidgetsChangedEvent();
    }
    /** @internal */
    get widgetCount() {
        return this._widgets.length;
    }
    /** @internal */
    get widgets() { return this._widgets; }
    set widgets(w) {
        this._widgets = w;
        this.onWidgetsChanged.emit({ items: w });
    }
    /** Adds a WidgetDef for use in a Frontstage.
     * @note Added `widgetDef` must return unique id to correctly save/restore App layout.
     * Semi-stable id is generated when auto-generated `widgetDef` id is detected,
     * but correctness of such id depends on `addWidgetDef` call order and widget location.
     */
    addWidgetDef(widgetDef, stageId, stageUsage, location, section) {
        if (stageId === undefined && stageUsage === undefined) {
            Logger.logError(UiFramework.loggerCategory(this), `addWidgetDef: stageId or stageUsage param must be specified`);
            return false;
        }
        section = (section !== undefined) ? section : StagePanelSection.Start;
        const index = this._widgets.reduce((acc, info) => {
            if (info.stageId === stageId && info.stageUsage === stageUsage && info.location === location && info.section === section)
                return acc + 1;
            return acc;
        }, 0);
        const stableId = getWidgetManagerStableWidgetId(stageUsage, location, section, index);
        const stableWidget = createStableWidgetDef(widgetDef, stableId);
        const newWidget = { widgetDef: stableWidget, stageId, stageUsage, location, section };
        const oldWidgets = this._widgets.filter((info) => info.widgetDef.id !== newWidget.widgetDef.id);
        const updatedWidgets = [
            ...oldWidgets,
            newWidget,
        ];
        this.widgets = updatedWidgets;
        return true;
    }
    /** Removes a WidgetDef.
     */
    removeWidgetDef(widgetId) {
        let result = false;
        const updatedWidgets = this._widgets.filter((info) => info.widgetDef.id !== widgetId);
        if (updatedWidgets.length !== this._widgets.length) {
            this.widgets = updatedWidgets;
            result = true;
        }
        return result;
    }
    // Used when WidgetDefs are requested from UiItemProviders when uiVersion="1"
    // istanbul ignore next
    getStagePanelLocationFromZoneLocation(location) {
        switch (location) {
            case ZoneLocation.BottomCenter:
            case ZoneLocation.TopCenter:
            case ZoneLocation.TopRight:
            case ZoneLocation.TopLeft:
                return undefined; // an existing stage does not support appending widgets to these zones
            case ZoneLocation.BottomLeft:
            case ZoneLocation.CenterLeft:
                return StagePanelLocation.Left;
            case ZoneLocation.BottomRight:
            case ZoneLocation.CenterRight:
                return StagePanelLocation.Right;
        }
    }
    /** Gets WidgetDefs for a Frontstage location.
     */
    getWidgetDefs(stageId, stageUsage, location, section, frontstageApplicationData) {
        const definedSection = section === undefined ? StagePanelSection.Start : section;
        const widgetInfos = this._widgets.filter((info) => {
            return (!info.stageId || info.stageId === stageId)
                && (!info.stageUsage || info.stageUsage === stageUsage)
                && info.location === location
                && info.section === definedSection;
        });
        const widgetDefs = widgetInfos.map((info) => info.widgetDef);
        // Consult the UiItemsManager to get any Abstract widgets
        if (location in StagePanelLocation) {
            const widgets = UiItemsManager.getWidgets(stageId, stageUsage, location, definedSection, undefined, frontstageApplicationData);
            widgets.forEach((abstractProps, index) => {
                const props = WidgetDef.createWidgetPropsFromAbstractProps(abstractProps);
                const stableId = getAddonStableWidgetId(stageUsage, location, definedSection, index);
                const stableProps = getStableWidgetProps(props, stableId);
                const wd = new WidgetDef(stableProps);
                widgetDefs.push(wd);
            });
        }
        else {
            // istanbul ignore else
            if (location in ZoneLocation) {
                const panelLocation = this.getStagePanelLocationFromZoneLocation(location);
                // istanbul ignore else
                if (panelLocation && location in AbstractZoneLocation) {
                    const widgets = UiItemsManager.getWidgets(stageId, stageUsage, panelLocation, undefined, location, frontstageApplicationData);
                    widgets.forEach((abstractProps, index) => {
                        const props = WidgetDef.createWidgetPropsFromAbstractProps(abstractProps);
                        const stableId = getAddonStableWidgetId(stageUsage, location, definedSection, index);
                        const stableProps = getStableWidgetProps(props, stableId);
                        const wd = new WidgetDef(stableProps);
                        widgetDefs.push(wd);
                    });
                }
            }
        }
        return widgetDefs.length > 0 ? widgetDefs : undefined;
    }
}
//# sourceMappingURL=WidgetManager.js.map