"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 Widget
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.WidgetDef = exports.WidgetType = exports.WidgetStateChangedEvent = void 0;
const appui_abstract_1 = require("@itwin/appui-abstract");
const ConfigurableUiControl_1 = require("../configurableui/ConfigurableUiControl");
const SyncUiEventDispatcher_1 = require("../syncui/SyncUiEventDispatcher");
const UiFramework_1 = require("../UiFramework");
const PropsHelper_1 = require("../utils/PropsHelper");
const StatusBarWidgetComposerControl_1 = require("./StatusBarWidgetComposerControl");
const core_react_1 = require("@itwin/core-react");
const InternalFrontstageManager_1 = require("../frontstage/InternalFrontstageManager");
/* eslint-disable deprecation/deprecation */
const widgetStateNameMap = new Map([
    [appui_abstract_1.WidgetState.Closed, "Closed"],
    [appui_abstract_1.WidgetState.Floating, "Floating"],
    [appui_abstract_1.WidgetState.Hidden, "Hidden"],
    [appui_abstract_1.WidgetState.Open, "Open"],
    [appui_abstract_1.WidgetState.Unloaded, "Unloaded"],
]);
/** Widget State Changed Event class.
 * @public
 */
class WidgetStateChangedEvent extends appui_abstract_1.UiEvent {
}
exports.WidgetStateChangedEvent = WidgetStateChangedEvent;
/** Widget type enum.
 * @public
 */
var WidgetType;
(function (WidgetType) {
    WidgetType[WidgetType["Tool"] = 0] = "Tool";
    WidgetType[WidgetType["Navigation"] = 1] = "Navigation";
    /** @deprecated in 3.6. UI 1.0 will be removed in AppUi 4.0 */
    WidgetType[WidgetType["FreeFrom"] = 2] = "FreeFrom";
    WidgetType[WidgetType["Rectangular"] = 3] = "Rectangular";
    WidgetType[WidgetType["ToolSettings"] = 4] = "ToolSettings";
    WidgetType[WidgetType["StatusBar"] = 5] = "StatusBar";
})(WidgetType = exports.WidgetType || (exports.WidgetType = {}));
// -----------------------------------------------------------------------------
/** A Widget Definition in the 9-Zone Layout system.
 * @public
 */
class WidgetDef {
    /** @internal */
    constructor(widgetProps) {
        this._label = "";
        this._tooltip = "";
        this._defaultState = appui_abstract_1.WidgetState.Unloaded;
        this._state = appui_abstract_1.WidgetState.Unloaded;
        this._classId = undefined;
        this._priority = 0;
        this._isFreeform = false;
        this._isFloatingStateSupported = false;
        this._isFloatingStateWindowResizable = true;
        this._isToolSettings = false;
        this._isStatusBar = false;
        this._stateChanged = false;
        this._fillZone = false;
        this._syncEventIds = [];
        this._widgetType = WidgetType.Rectangular;
        this._defaultTabLocation = {
            side: "left",
            tabIndex: 0,
            widgetId: "",
            widgetIndex: 0,
        };
        this._handleSyncUiEvent = (args) => {
            if ((this.syncEventIds.length > 0) && this.syncEventIds.some((value) => args.eventIds.has(value.toLowerCase()))) { // eslint-disable-line deprecation/deprecation
                // istanbul ignore else
                if (this.stateFunc) { // eslint-disable-line deprecation/deprecation
                    let newState = this.state;
                    newState = this.stateFunc(newState); // eslint-disable-line deprecation/deprecation
                    this.setWidgetState(newState);
                }
            }
        };
        WidgetDef._sId++;
        this._id = `Widget-${WidgetDef._sId}`;
        if (widgetProps)
            WidgetDef.initializeFromWidgetProps(widgetProps, this); // eslint-disable-line deprecation/deprecation
    }
    get state() {
        if ("1" === UiFramework_1.UiFramework.uiVersion) // eslint-disable-line deprecation/deprecation
            return this._state;
        const frontstageDef = UiFramework_1.UiFramework.frontstages.activeFrontstageDef;
        if (frontstageDef && frontstageDef.findWidgetDef(this.id)) {
            const currentState = frontstageDef.getWidgetCurrentState(this);
            // istanbul ignore else
            if (undefined !== currentState)
                return currentState;
        }
        return this.defaultState;
    }
    get id() { return this._id; }
    get classId() { return this._classId; }
    get priority() { return this._priority; }
    /** @deprecated in 3.6. UI 1.0 will be removed in AppUi 4.0*/
    get isFreeform() { return this._isFreeform; }
    get isFloatingStateSupported() { return this._isFloatingStateSupported; }
    get isFloatingStateWindowResizable() { return this._isFloatingStateWindowResizable; }
    get isToolSettings() { return this._isToolSettings; }
    get isStatusBar() { return this._isStatusBar; }
    get stateChanged() { return this._stateChanged; }
    /** @deprecated in 3.6. UI1.0 is deprecated. */
    get fillZone() { return this._fillZone; }
    /** @deprecated in 3.6. UI 1.0 will be removed in AppUi 4.0*/
    get syncEventIds() { return this._syncEventIds; }
    /** @deprecated in 3.6. UI 1.0 will be removed in AppUi 4.0*/
    get stateFunc() { return this._stateFunc; } // eslint-disable-line deprecation/deprecation
    get applicationData() { return this._applicationData; }
    get isFloating() { return this.state === appui_abstract_1.WidgetState.Floating; }
    get iconSpec() { return this._iconSpec === core_react_1.IconHelper.reactIconKey ? core_react_1.IconHelper.getIconReactNode(this._iconSpec, this._internalData) : this._iconSpec; }
    set iconSpec(spec) { this._iconSpec = this._internalData ? core_react_1.IconHelper.getIconData(spec, this._internalData) : spec; }
    get badgeType() { return this._badgeType; }
    get initialProps() { return this._initialProps; } // eslint-disable-line deprecation/deprecation
    get widgetType() { return this._widgetType; }
    set widgetType(type) { this._widgetType = type; }
    /** @internal */
    get tabLocation() { return this._tabLocation; }
    set tabLocation(tabLocation) { this._tabLocation = tabLocation; }
    /** @internal */
    get defaultTabLocation() { return this._defaultTabLocation; }
    /** @internal */
    get defaultFloatingPosition() { return this._defaultFloatingPosition; }
    set defaultFloatingPosition(position) { this._defaultFloatingPosition = position; }
    /** @internal */
    get defaultFloatingSize() { return this._defaultFloatingSize; }
    set defaultFloatingSize(size) { this._defaultFloatingSize = size; }
    /** @internal */
    get defaultState() { return this._defaultState; }
    /** @internal */
    get popoutBounds() { return this._popoutBounds; }
    set popoutBounds(bounds) { this._popoutBounds = bounds; }
    /** @deprecated in 3.5. UI 1.0 will be removed in AppUi 4.0 */
    static initializeFromWidgetProps(widgetProps, me) {
        me._initialProps = widgetProps;
        if (widgetProps.id !== undefined)
            me._id = widgetProps.id;
        if (widgetProps.label)
            me.setLabel(widgetProps.label);
        else if (widgetProps.labelKey)
            me._label = UiFramework_1.UiFramework.localization.getLocalizedString(widgetProps.labelKey);
        me.setCanPopout(widgetProps.canPopout);
        me.setFloatingContainerId(widgetProps.floatingContainerId);
        me.defaultFloatingPosition = widgetProps.defaultFloatingPosition ? widgetProps.defaultFloatingPosition : undefined;
        me._hideWithUiWhenFloating = !!widgetProps.hideWithUiWhenFloating;
        me.allowedPanelTargets = widgetProps.allowedPanelTargets;
        if (widgetProps.priority !== undefined)
            me._priority = widgetProps.priority;
        if (widgetProps.tooltip)
            me.setTooltip(widgetProps.tooltip);
        else if (widgetProps.tooltipKey)
            me._tooltip = UiFramework_1.UiFramework.localization.getLocalizedString(widgetProps.tooltipKey);
        if (widgetProps.control !== undefined)
            me._classId = widgetProps.control;
        else if (widgetProps.classId !== undefined)
            me._classId = widgetProps.classId;
        if (widgetProps.defaultState !== undefined) {
            me._defaultState = widgetProps.defaultState;
            // istanbul ignore next
            if ("1" === UiFramework_1.UiFramework.uiVersion) // eslint-disable-line deprecation/deprecation
                me._state = widgetProps.defaultState === appui_abstract_1.WidgetState.Floating ? appui_abstract_1.WidgetState.Open : widgetProps.defaultState;
        }
        if (widgetProps.isFreeform !== undefined) { // eslint-disable-line deprecation/deprecation
            me._isFreeform = widgetProps.isFreeform; // eslint-disable-line deprecation/deprecation
            me._widgetType = me.isFreeform ? WidgetType.FreeFrom : WidgetType.Rectangular; // eslint-disable-line deprecation/deprecation
        }
        if (widgetProps.isFloatingStateSupported !== undefined)
            me._isFloatingStateSupported = widgetProps.isFloatingStateSupported;
        if (widgetProps.isFloatingStateWindowResizable !== undefined)
            me._isFloatingStateWindowResizable = widgetProps.isFloatingStateWindowResizable;
        if (widgetProps.isToolSettings !== undefined)
            me._isToolSettings = widgetProps.isToolSettings;
        if (widgetProps.isStatusBar !== undefined)
            me._isStatusBar = widgetProps.isStatusBar;
        if (widgetProps.fillZone !== undefined)
            me._fillZone = widgetProps.fillZone;
        if (widgetProps.applicationData !== undefined)
            me._applicationData = widgetProps.applicationData;
        if (widgetProps.element !== undefined)
            me._widgetReactNode = widgetProps.element;
        if (widgetProps.iconSpec !== undefined)
            me._iconSpec = widgetProps.iconSpec;
        if (widgetProps.internalData)
            me._internalData = widgetProps.internalData;
        // istanbul ignore next
        if (widgetProps.icon !== undefined && me._iconSpec === undefined)
            me._iconSpec = widgetProps.icon;
        if (widgetProps.badgeType !== undefined)
            me._badgeType = widgetProps.badgeType;
        me._preferredPanelSize = widgetProps.preferredPanelSize;
        me._defaultFloatingSize = widgetProps.defaultFloatingSize;
        me._onWidgetStateChanged = widgetProps.onWidgetStateChanged;
        me._saveTransientState = widgetProps.saveTransientState;
        me._restoreTransientState = widgetProps.restoreTransientState;
        me.setUpSyncSupport(widgetProps); // eslint-disable-line deprecation/deprecation
    }
    /** @deprecated in 3.5. UI 1.0 will be removed in AppUi 4.0 */
    static createWidgetPropsFromAbstractProps(abstractWidgetProps) {
        const widgetProps = abstractWidgetProps; // eslint-disable-line deprecation/deprecation
        widgetProps.element = abstractWidgetProps.getWidgetContent();
        return widgetProps;
    }
    /** @deprecated in 3.5. UI 1.0 will be removed in AppUi 4.0 */
    setUpSyncSupport(props) {
        if (props.stateFunc && props.syncEventIds && props.syncEventIds.length > 0) { // eslint-disable-line deprecation/deprecation
            this._syncEventIds = props.syncEventIds;
            this._stateFunc = props.stateFunc; // eslint-disable-line deprecation/deprecation
            SyncUiEventDispatcher_1.SyncUiEventDispatcher.onSyncUiEvent.addListener(this._handleSyncUiEvent);
        }
    }
    /** @alpha */
    get preferredPanelSize() {
        return this._preferredPanelSize;
    }
    /** Get the label string */
    get label() {
        return PropsHelper_1.PropsHelper.getStringFromSpec(this._label);
    }
    /** Set the label.
     * @param v A string or a function to get the string.
     */
    setLabel(v) {
        if (this._label === v)
            return;
        this._label = v;
        InternalFrontstageManager_1.InternalFrontstageManager.onWidgetLabelChangedEvent.emit({ widgetDef: this });
    }
    /** Get the tooltip string */
    get tooltip() {
        return PropsHelper_1.PropsHelper.getStringFromSpec(this._tooltip);
    }
    /** Set the tooltip.
     * @param v A string or a function to get the string.
     */
    setTooltip(v) {
        this._tooltip = v;
    }
    get widgetControl() {
        return this._widgetControl;
    }
    getWidgetControl(type) {
        if (!this._widgetControl && this.classId) {
            let usedClassId = "";
            if (typeof this.classId === "string") {
                // istanbul ignore else
                if (this.classId)
                    this._widgetControl = UiFramework_1.UiFramework.controls.create(this.classId, this.id, this.applicationData);
                usedClassId = this.classId;
            }
            else {
                const info = new ConfigurableUiControl_1.ConfigurableCreateInfo(this.classId.name, this.id, this.id);
                usedClassId = this.classId.name;
                this._widgetControl = new this.classId(info, this.applicationData);
            }
            // istanbul ignore else
            if (this._widgetControl) {
                if (this._widgetControl.getType() !== type) {
                    throw new appui_abstract_1.UiError(UiFramework_1.UiFramework.loggerCategory(this), `getWidgetControl: '${usedClassId}' is NOT a ${type}; it is a ${this._widgetControl.getType()}`);
                }
                this._widgetControl.widgetDef = this;
                this._widgetControl.initialize();
            }
        }
        // istanbul ignore next - To avoid breaking API changes, if a WidgetControl is not specified for a status bar use Default one.
        if (!this._widgetControl && this.isStatusBar) {
            const info = new ConfigurableUiControl_1.ConfigurableCreateInfo("StatusBarWidgetComposerControl", StatusBarWidgetComposerControl_1.StatusBarWidgetComposerControl.controlId, StatusBarWidgetComposerControl_1.StatusBarWidgetComposerControl.controlId);
            this._widgetControl = new StatusBarWidgetComposerControl_1.StatusBarWidgetComposerControl(info, undefined);
            this._widgetControl.widgetDef = this;
            this._widgetControl.initialize();
        }
        return this._widgetControl;
    }
    get reactNode() {
        if (!this._widgetReactNode) {
            const widgetControl = this.getWidgetControl(ConfigurableUiControl_1.ConfigurableUiControlType.Widget);
            // istanbul ignore else
            if (widgetControl && widgetControl.reactNode)
                this._widgetReactNode = widgetControl.reactNode;
        }
        return this._widgetReactNode;
    }
    set reactNode(node) {
        this._widgetReactNode = node;
    }
    setWidgetState(newState) {
        if (this.state === newState)
            return;
        if ("1" === UiFramework_1.UiFramework.uiVersion) // eslint-disable-line deprecation/deprecation
            this._state = newState;
        this._stateChanged = true;
        UiFramework_1.UiFramework.frontstages.onWidgetStateChangedEvent.emit({ widgetDef: this, widgetState: newState });
        this.onWidgetStateChanged();
    }
    setCanPopout(value) {
        this._canPopout = value;
    }
    get canPopout() {
        return (this._canPopout);
    }
    setFloatingContainerId(value) {
        this._floatingContainerId = value;
    }
    get floatingContainerId() {
        return (this._floatingContainerId);
    }
    canOpen() {
        return (this.isFloating || this.isActive);
    }
    get isVisible() {
        return appui_abstract_1.WidgetState.Hidden !== this.state;
    }
    get activeState() {
        return this.state;
    }
    get isActive() {
        return appui_abstract_1.WidgetState.Open === this.activeState;
    }
    set hideWithUiWhenFloating(hide) {
        this._hideWithUiWhenFloating = !!hide;
    }
    get hideWithUiWhenFloating() {
        return !!this._hideWithUiWhenFloating;
    }
    get allowedPanelTargets() {
        return this._allowedPanelTargets;
    }
    set allowedPanelTargets(targets) {
        this._allowedPanelTargets = (targets && (targets === null || targets === void 0 ? void 0 : targets.length) > 0) ? targets : undefined;
    }
    onWidgetStateChanged() {
        // eslint-disable-next-line @typescript-eslint/no-floating-promises
        this.widgetControl && UiFramework_1.UiFramework.postTelemetry(`Widget ${this.widgetControl.classId} state set to ${widgetStateNameMap.get(this.state)}`, "35402486-9839-441E-A5C7-46D546142D11");
        this.widgetControl && this.widgetControl.onWidgetStateChanged();
        // istanbul ignore next
        this._onWidgetStateChanged && this._onWidgetStateChanged();
    }
    /** Overwrite to save transient DOM state (i.e. scroll offset). */
    saveTransientState() {
        this.widgetControl && this.widgetControl.saveTransientState();
        this._saveTransientState && this._saveTransientState();
    }
    /** Overwrite to restore transient DOM state.
     * @note Return true if the state is restored or the Widget will remount.
     */
    restoreTransientState() {
        let result = true;
        if (this.widgetControl || this._restoreTransientState) {
            let result1 = false, result2 = false;
            if (this.widgetControl)
                result1 = this.widgetControl.restoreTransientState();
            if (this._restoreTransientState)
                result2 = this._restoreTransientState();
            result = !(result1 || result2);
        }
        return result;
    }
    /** Opens the widget and makes it visible to the user.
     * I.e. opens the stage panel or brings the floating widget to front of the screen.
     * @alpha
     */
    show() {
        InternalFrontstageManager_1.InternalFrontstageManager.onWidgetShowEvent.emit({ widgetDef: this });
    }
    /** Opens the widget and expands it to fill full size of the stage panel.
     * @alpha
     */
    expand() {
        InternalFrontstageManager_1.InternalFrontstageManager.onWidgetExpandEvent.emit({ widgetDef: this });
    }
}
exports.WidgetDef = WidgetDef;
WidgetDef._sId = 0;
//# sourceMappingURL=WidgetDef.js.map