/*---------------------------------------------------------------------------------------------
 * 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
 */
/* eslint-disable deprecation/deprecation, @typescript-eslint/ban-ts-comment */
import * as abstract from "@itwin/appui-abstract";
import { assert } from "@itwin/core-bentley";
import { BadgeType, IconHelper } from "@itwin/core-react";
import { StagePanelLocation } from "../stagepanels/StagePanelLocation";
import { StagePanelSection } from "../stagepanels/StagePanelSection";
import { isToolbarActionItem, isToolbarGroupItem, } from "../toolbar/ToolbarItem";
import { isStatusBarCustomItem } from "../statusbar/StatusBarItem";
const _abstract = abstract;
// @ts-ignore Removed in 4.0
const AbstractUiItemsManager = _abstract.UiItemsManager;
// @ts-ignore Removed in 4.0
const isAbstractStatusBarCustomItem = _abstract.isAbstractStatusBarCustomItem;
// @ts-ignore Removed in 4.0
const AbstractStagePanelLocation = _abstract.StagePanelLocation; // eslint-disable-line @typescript-eslint/no-redeclare
// @ts-ignore Removed in 4.0
const AbstractStagePanelSection = _abstract.StagePanelSection; // eslint-disable-line @typescript-eslint/no-redeclare
const AbstractToolbarItemUtilities = abstract.ToolbarItemUtilities;
const originalDataSymbol = Symbol("originalData");
/** @internal */
export function createAbstractUiItemsManagerAdapter() {
    if (!AbstractUiItemsManager)
        return undefined;
    return new AbstractUiItemsManagerAdapter(AbstractUiItemsManager);
}
class AbstractUiItemsManagerAdapter {
    constructor(_adaptee) {
        this._adaptee = _adaptee;
    }
    clearAllProviders() {
        return this._adaptee.clearAllProviders();
    }
    get onUiProviderRegisteredEvent() {
        if (!("emit" in this._adaptee.onUiProviderRegisteredEvent)) {
            this._adaptee.onUiProviderRegisteredEvent.emit = (args) => {
                this._adaptee.onUiProviderRegisteredEvent.raiseEvent(args);
            };
        }
        return this._adaptee
            .onUiProviderRegisteredEvent;
    }
    unregister(providerId) {
        return this._adaptee.unregister(providerId);
    }
    get hasRegisteredProviders() {
        return this._adaptee.hasRegisteredProviders;
    }
    get registeredProviderIds() {
        return this._adaptee.registeredProviderIds;
    }
    register(provider, overrides) {
        const abstractProvider = createUiItemsProviderToAbstractAdapter(provider);
        return this._adaptee.register(abstractProvider, overrides);
    }
    getUiItemsProvider(providerId) {
        const abstractProvider = this._adaptee.getUiItemsProvider(providerId);
        if (!abstractProvider)
            return undefined;
        const provider = createAbstractToUiItemsProviderAdapter(abstractProvider);
        return provider;
    }
    getBackstageItems() {
        const abstractItems = this._adaptee.getBackstageItems();
        // @ts-ignore Possibly 'any'
        const items = abstractItems.map((abstractItem) => {
            const item = fromAbstractBackstageItem(abstractItem);
            return {
                ...item,
                providerId: abstractItem.providerId ? abstractItem.providerId : "",
            };
        });
        return items;
    }
    getStatusBarItems(stageId, stageUsage) {
        const abstractItems = this._adaptee.getStatusBarItems(stageId, stageUsage);
        // @ts-ignore Possibly 'any'
        const items = abstractItems.map((abstractItem) => {
            const item = fromAbstractStatusBarItem(abstractItem);
            return {
                ...item,
                providerId: abstractItem.providerId ? abstractItem.providerId : "",
            };
        });
        return items;
    }
    getToolbarButtonItems(stageId, stageUsage, usage, orientation) {
        const abstractItems = this._adaptee.getToolbarButtonItems(stageId, stageUsage, usage, orientation);
        // @ts-ignore Possibly 'any'
        const items = abstractItems.map((abstractItem) => {
            const item = fromAbstractToolbarItem(abstractItem);
            return {
                ...item,
                providerId: abstractItem.providerId ?? "",
            };
        });
        return items;
    }
    getWidgets(stageId, stageUsage, location, section) {
        const abstractLocations = toAbstractStagePanelLocation(location);
        const abstractSections = section === undefined
            ? [undefined]
            : toAbstractStagePanelSection(section);
        const combos = [];
        abstractLocations.forEach((abstractLocation) => {
            abstractSections.forEach((abstractSection) => {
                combos.push([abstractLocation, abstractSection]);
            });
        });
        let abstractWidgets = combos.reduce((acc, [abstractLocation, abstractSection]) => {
            const w = this._adaptee.getWidgets(stageId, stageUsage, abstractLocation, abstractSection);
            acc.push(...w);
            return acc;
        }, []);
        abstractWidgets = abstractWidgets.reduce((acc, abstractWidget) => {
            if (-1 === acc.findIndex((w) => w.id === abstractWidget.id))
                acc.push(abstractWidget);
            return acc;
        }, []);
        const widgets = abstractWidgets
            // @ts-ignore Possibly 'any'
            .map((abstractWidget) => {
            const widget = fromAbstractWidget(abstractWidget);
            return {
                ...widget,
                providerId: abstractWidget.providerId ?? "",
            };
        });
        return widgets;
    }
}
function createUiItemsProviderToAbstractAdapter(adaptee) {
    const { id, onUnregister, provideBackstageItems, provideStatusBarItems, provideWidgets, ...other } = adaptee;
    const provider = createGetPropertyAdapter(adaptee);
    return {
        id: adaptee.id,
        onUnregister: adaptee.onUnregister,
        provideBackstageItems: () => {
            const items = provider.provideBackstageItems();
            const abstractItems = items.map((item) => toAbstractBackstageItem(item));
            return abstractItems;
        },
        provideStatusBarItems: (stageId, stageUsage, _stageAppData) => {
            const items = provider.provideStatusBarItems(stageId, stageUsage);
            const abstractItems = items.map((item) => toAbstractStatusBarItem(item));
            return abstractItems;
        },
        provideToolbarButtonItems: (stageId, stageUsage, usage, orientation, _stageAppData) => {
            const items = provider.provideToolbarItems(stageId, stageUsage, usage, orientation);
            const abstractItems = items.map((item) => toAbstractToolbarItem(item));
            return abstractItems;
        },
        provideWidgets: (stageId, stageUsage, abstractLocation, abstractSection, _zoneLocation, _stageAppData) => {
            const location = fromAbstractStagePanelLocation(abstractLocation);
            const section = abstractSection === undefined
                ? undefined
                : fromAbstractStagePanelSection(abstractSection);
            const items = provider.provideWidgets(stageId, stageUsage, location, section);
            const abstractWidgets = items.map((item) => toAbstractWidget(item));
            return abstractWidgets;
        },
        ...other,
    };
}
function createAbstractToUiItemsProviderAdapter(adaptee) {
    const { id, onUnregister, provideBackstageItems, provideStatusBarItems, provideWidgets, ...other } = adaptee;
    return {
        id: adaptee.id,
        onUnregister: adaptee.onUnregister,
        provideBackstageItems: () => {
            if (!adaptee.provideBackstageItems)
                return [];
            const abstractItems = adaptee.provideBackstageItems();
            // @ts-ignore Possibly 'any'
            const items = abstractItems.map((abstractItem) => fromAbstractBackstageItem(abstractItem));
            return items;
        },
        provideStatusBarItems: (stageId, stageUsage) => {
            if (!adaptee.provideStatusBarItems)
                return [];
            const abstractItems = adaptee.provideStatusBarItems(stageId, stageUsage);
            // @ts-ignore Possibly 'any'
            const items = abstractItems.map((abstractItem) => fromAbstractStatusBarItem(abstractItem));
            return items;
        },
        provideWidgets: (stageId, stageUsage, location, section) => {
            if (!adaptee.provideWidgets)
                return [];
            const abstractLocations = toAbstractStagePanelLocation(location);
            const abstractSections = section === undefined
                ? [undefined]
                : toAbstractStagePanelSection(section);
            const combos = [];
            abstractLocations.forEach((abstractLocation) => {
                abstractSections.forEach((abstractSection) => {
                    combos.push([abstractLocation, abstractSection]);
                });
            });
            let abstractWidgets = combos.reduce((acc, [abstractLocation, abstractSection]) => {
                assert(!!adaptee.provideWidgets);
                const w = adaptee.provideWidgets(stageId, stageUsage, abstractLocation, abstractSection);
                acc.push(...w);
                return acc;
            }, []);
            abstractWidgets = abstractWidgets.reduce((acc, abstractWidget) => {
                if (-1 === acc.findIndex((w) => w.id === abstractWidget.id))
                    acc.push(abstractWidget);
                return acc;
            }, []);
            const widgets = abstractWidgets.map((abstractWidget) => fromAbstractWidget(abstractWidget));
            return widgets;
        },
        provideToolbarItems: (stageId, stageUsage, usage, orientation) => {
            if (!adaptee.provideToolbarButtonItems)
                return [];
            const abstractItems = adaptee.provideToolbarButtonItems(stageId, stageUsage, usage, orientation);
            // @ts-ignore Possibly 'any'
            const items = abstractItems.map((abstractItem) => fromAbstractToolbarItem(abstractItem));
            return items;
        },
        ...other,
    };
}
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
function getBadgeType(badgeKind) {
    switch (badgeKind) {
        case "new":
            return BadgeType.New;
        case "technical-preview":
            return BadgeType.TechnicalPreview;
        default:
            return undefined;
    }
}
function toAbstractBackstageItem(item) {
    let abstractItem = getOriginalData(item);
    if (abstractItem)
        return abstractItem;
    const internalData = new Map();
    const icon = IconHelper.getIconData(item.icon, internalData);
    abstractItem = {
        ...item,
        badgeType: getBadgeType(item.badgeKind) || item.badge,
        icon,
        internalData,
    };
    setOriginalData(abstractItem, item);
    return abstractItem;
}
function toAbstractStatusBarItem(item) {
    let abstractItem = getOriginalData(item);
    if (abstractItem)
        return abstractItem;
    if (isStatusBarCustomItem(item)) {
        abstractItem = {
            ...item,
            badgeType: getBadgeType(item.badgeKind) || item.badge,
            isCustom: true,
            reactNode: item.content,
        };
    }
    else {
        const internalData = new Map();
        const icon = IconHelper.getIconData(item.icon, internalData);
        abstractItem = {
            ...item,
            badgeType: getBadgeType(item.badgeKind) || item.badge,
            icon,
            internalData,
        };
    }
    setOriginalData(abstractItem, item);
    return abstractItem;
}
function toAbstractToolbarItem(item) {
    let abstractItem = getOriginalData(item);
    if (abstractItem)
        return abstractItem;
    const internalData = new Map();
    const icon = IconHelper.getIconData(item.icon, internalData);
    if (isToolbarActionItem(item)) {
        abstractItem = {
            ...item,
            badgeType: getBadgeType(item.badgeKind) || item.badge,
            icon,
            internalData,
            parentToolGroupId: item.parentGroupItemId,
        };
    }
    else if (isToolbarGroupItem(item)) {
        abstractItem = {
            ...item,
            badgeType: getBadgeType(item.badgeKind) || item.badge,
            icon,
            internalData,
            parentToolGroupId: item.parentGroupItemId,
            items: item.items.map((i) => toAbstractToolbarItem(i)),
        };
    }
    else {
        abstractItem = {
            ...item,
            badgeType: getBadgeType(item.badgeKind) || item.badge,
            isCustom: true,
            icon,
            internalData,
        };
    }
    setOriginalData(abstractItem, item);
    return abstractItem;
}
function toAbstractWidget(widget) {
    let abstractWidget = getOriginalData(widget);
    if (abstractWidget)
        return abstractWidget;
    const allowedPanelTargets = widget.allowedPanels
        // @ts-ignore Possibly 'any'
        ?.map((location) => {
        const map = {
            [StagePanelLocation.Top]: "top",
            [StagePanelLocation.Left]: "left",
            [StagePanelLocation.Right]: "right",
            [StagePanelLocation.Bottom]: "bottom",
        };
        // @ts-ignore Possibly 'any'
        return map[location];
    });
    const internalData = new Map();
    const icon = IconHelper.getIconData(widget.icon, internalData);
    abstractWidget = {
        ...widget,
        id: widget.id ?? "",
        getWidgetContent: () => widget.content,
        allowedPanelTargets,
        badgeType: getBadgeType(widget.badgeKind) || widget.badge,
        defaultFloatingPosition: typeof widget.canFloat === "object"
            ? widget.canFloat.defaultPosition
            : undefined,
        defaultFloatingSize: typeof widget.canFloat === "object"
            ? widget.canFloat.defaultSize
            : undefined,
        floatingContainerId: typeof widget.canFloat === "object"
            ? widget.canFloat.containerId
            : undefined,
        hideWithUiWhenFloating: typeof widget.canFloat === "object"
            ? widget.canFloat.hideWithUi
            : undefined,
        isFloatingStateSupported: !!widget.canFloat,
        isFloatingStateWindowResizable: typeof widget.canFloat === "object"
            ? widget.canFloat.isResizable
            : undefined,
        icon,
        internalData,
    };
    setOriginalData(abstractWidget, widget);
    return abstractWidget;
}
function fromAbstractBackstageItem(abstractItem) {
    let item = getOriginalData(abstractItem);
    if (item)
        return item;
    const icon = fromAbstractIcon(abstractItem.icon, abstractItem.internalData);
    item = {
        ...abstractItem,
        badge: abstractItem.badgeType,
        icon,
    };
    assert(!!item);
    setOriginalData(item, abstractItem);
    return item;
}
function fromAbstractStatusBarItem(abstractItem) {
    let item = getOriginalData(abstractItem);
    if (item)
        return item;
    if (isAbstractStatusBarCustomItem(abstractItem)) {
        const content = abstractItem
            .reactNode;
        return {
            ...abstractItem,
            badge: abstractItem.badgeType,
            content,
        };
    }
    else {
        const icon = fromAbstractIcon(abstractItem.icon, abstractItem.internalData);
        item = {
            ...abstractItem,
            badge: abstractItem.badgeType,
            icon,
        };
    }
    assert(!!item);
    setOriginalData(item, abstractItem);
    return item;
}
function fromAbstractToolbarItem(abstractItem) {
    let item = getOriginalData(abstractItem);
    if (item)
        return item;
    const icon = fromAbstractIcon(abstractItem.icon, abstractItem.internalData);
    if (AbstractToolbarItemUtilities.isCustomDefinition(abstractItem)) {
        item = {
            ...abstractItem,
            badge: abstractItem.badgeType,
            icon,
        };
    }
    else {
        item = {
            ...abstractItem,
            badge: abstractItem.badgeType,
            parentGroupItemId: abstractItem.parentToolGroupId,
            icon,
        };
    }
    setOriginalData(item, abstractItem);
    return item;
}
function fromAbstractWidget(abstractWidget) {
    let widget = getOriginalData(abstractWidget);
    if (widget)
        return widget;
    const allowedPanels = abstractWidget.allowedPanelTargets
        // @ts-ignore Possibly 'any'
        ?.map((target) => {
        const map = {
            top: StagePanelLocation.Top,
            left: StagePanelLocation.Left,
            right: StagePanelLocation.Right,
            bottom: StagePanelLocation.Bottom,
        };
        // @ts-ignore Possibly 'any'
        return map[target];
    });
    const icon = fromAbstractIcon(abstractWidget.icon, abstractWidget.internalData);
    widget = {
        ...abstractWidget,
        id: abstractWidget.id ?? "",
        content: abstractWidget.getWidgetContent(),
        allowedPanels,
        badge: abstractWidget.badgeType,
        canFloat: abstractWidget.isFloatingStateSupported && {
            containerId: abstractWidget.floatingContainerId,
            defaultPosition: abstractWidget.defaultFloatingPosition,
            defaultSize: abstractWidget.defaultFloatingSize,
            hideWithUi: abstractWidget.hideWithUiWhenFloating,
            isResizable: abstractWidget.isFloatingStateWindowResizable,
        },
        icon,
    };
    assert(!!widget);
    setOriginalData(widget, abstractWidget);
    return widget;
}
function fromAbstractStagePanelLocation(location) {
    switch (location) {
        case AbstractStagePanelLocation.Left:
            return StagePanelLocation.Left;
        case AbstractStagePanelLocation.Top:
            return StagePanelLocation.Top;
        case AbstractStagePanelLocation.TopMost:
            return StagePanelLocation.Top;
        case AbstractStagePanelLocation.Bottom:
            return StagePanelLocation.Bottom;
        case AbstractStagePanelLocation.BottomMost:
            return StagePanelLocation.Bottom;
    }
    return StagePanelLocation.Right;
}
function toAbstractStagePanelLocation(location) {
    switch (location) {
        case StagePanelLocation.Left:
            return [AbstractStagePanelLocation.Left];
        case StagePanelLocation.Top:
            return [
                AbstractStagePanelLocation.Top,
                AbstractStagePanelLocation.TopMost,
            ];
        case StagePanelLocation.Bottom:
            return [
                AbstractStagePanelLocation.Bottom,
                AbstractStagePanelLocation.BottomMost,
            ];
    }
    return [AbstractStagePanelLocation.Right];
}
function fromAbstractStagePanelSection(section) {
    switch (section) {
        case AbstractStagePanelSection.End:
            return StagePanelSection.End;
    }
    return StagePanelSection.Start;
}
function toAbstractStagePanelSection(section) {
    switch (section) {
        case StagePanelSection.End:
            return [AbstractStagePanelSection.End];
    }
    return [AbstractStagePanelSection.Start, AbstractStagePanelSection.Middle];
}
function fromAbstractIcon(icon, internalData) {
    if (!icon)
        return undefined;
    const iconString = abstract.ConditionalStringValue.getValue(icon);
    if (!iconString)
        return undefined;
    if (iconString === IconHelper.reactIconKey && internalData)
        return internalData.get(IconHelper.reactIconKey);
    return iconString;
}
function getOriginalData(obj) {
    const originalData = obj[originalDataSymbol];
    if (!originalData)
        return undefined;
    return originalData;
}
function setOriginalData(obj, data) {
    obj[originalDataSymbol] = data;
}
/** Maps items of existing `get` properties to `provide` properties, otherwise uses `provide` properties.
 * @internal
 */
export function createGetPropertyAdapter(provider) {
    return {
        ...provider,
        provideBackstageItems: () => {
            return (provider.getBackstageItems?.() ??
                provider.provideBackstageItems?.() ??
                []);
        },
        provideStatusBarItems: (stageId, stageUsage) => {
            return (provider.getStatusBarItems?.() ??
                provider.provideStatusBarItems?.(stageId, stageUsage) ??
                []);
        },
        provideToolbarItems: (stageId, stageUsage, usage, orientation) => {
            if (provider.getToolbarItems) {
                return provider.getToolbarItems().filter((item) => {
                    const layout = item.layouts?.standard;
                    if (!layout)
                        return false;
                    return layout.usage === usage && layout.orientation === orientation;
                });
            }
            return (provider.provideToolbarItems?.(stageId, stageUsage, usage, orientation) ?? []);
        },
        provideWidgets: (stageId, stageUsage, location, section) => {
            if (provider.getWidgets) {
                return provider.getWidgets().filter((item) => {
                    const layout = item.layouts?.standard;
                    if (!layout)
                        return false;
                    return layout.location === location && layout.section === section;
                });
            }
            return (provider.provideWidgets?.(stageId, stageUsage, location, section) ?? []);
        },
    };
}
//# sourceMappingURL=AbstractUiItemsManager.js.map