"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 UiFramework_1 = require("../UiFramework");
const PropsHelper_1 = require("../utils/PropsHelper");
const core_react_1 = require("@itwin/core-react");
const InternalFrontstageManager_1 = require("../frontstage/InternalFrontstageManager");
const WidgetState_1 = require("./WidgetState");
const StagePanelLocation_1 = require("../stagepanels/StagePanelLocation");
const StatusBarWidgetComposerControl_1 = require("./StatusBarWidgetComposerControl");
/** 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";
    WidgetType[WidgetType["Rectangular"] = 2] = "Rectangular";
    WidgetType[WidgetType["ToolSettings"] = 3] = "ToolSettings";
    WidgetType[WidgetType["StatusBar"] = 4] = "StatusBar";
})(WidgetType = exports.WidgetType || (exports.WidgetType = {}));
// -----------------------------------------------------------------------------
/** A Widget Definition in the 9-Zone Layout system.
 * @public
 */
class WidgetDef {
    get 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;
    }
    get isFloatingStateSupported() {
        return this._isFloatingStateSupported;
    }
    get isFloatingStateWindowResizable() {
        return this._isFloatingStateWindowResizable;
    }
    get isToolSettings() {
        return this._widgetType === WidgetType.ToolSettings;
    }
    get isStatusBar() {
        return this._widgetType === WidgetType.StatusBar;
    }
    get stateChanged() {
        return this._stateChanged;
    }
    get applicationData() {
        return this._applicationData;
    }
    get isFloating() {
        return this.state === WidgetState_1.WidgetState.Floating;
    }
    get iconSpec() {
        return this._icon === core_react_1.IconHelper.reactIconKey
            ? core_react_1.IconHelper.getIconReactNode(this._icon, this._internalData)
            : this._icon;
    }
    set iconSpec(spec) {
        this._icon = this._internalData
            ? core_react_1.IconHelper.getIconData(spec, this._internalData)
            : spec;
    }
    get badgeType() {
        return this._badge;
    }
    get initialConfig() {
        return this._initialConfig;
    }
    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;
    }
    constructor() {
        this._label = "";
        this._tooltip = "";
        this._defaultState = WidgetState_1.WidgetState.Unloaded;
        this._classId = undefined;
        this._priority = 0;
        this._isFloatingStateSupported = false;
        this._isFloatingStateWindowResizable = true;
        this._stateChanged = false;
        this._widgetType = WidgetType.Rectangular;
        this._defaultTabLocation = {
            side: "left",
            tabIndex: 0,
            widgetId: "",
            widgetIndex: 0,
        };
        WidgetDef._sId++;
        this._id = `Widget-${WidgetDef._sId}`;
    }
    /** @internal */
    static create(config, type = WidgetType.Rectangular) {
        const def = new WidgetDef();
        def.initializeFromConfig(config, type);
        return def;
    }
    initializeFromConfig(config, type) {
        this._widgetType = type;
        this._initialConfig = config;
        this._id = config.id;
        if (config.label)
            this.setLabel(config.label);
        else if (config.labelKey)
            this._label = UiFramework_1.UiFramework.localization.getLocalizedString(config.labelKey);
        else if (type === WidgetType.ToolSettings)
            this.setLabel("Tool Settings");
        this.setCanPopout(config.canPopout);
        const canFloat = config.canFloat;
        this._isFloatingStateSupported = !!canFloat;
        if (typeof canFloat === "object") {
            this.setFloatingContainerId(canFloat.containerId);
            this.defaultFloatingPosition = canFloat.defaultPosition;
            this._hideWithUiWhenFloating = !!canFloat.hideWithUi;
            this._isFloatingStateWindowResizable = !!canFloat.isResizable;
            this._defaultFloatingSize = canFloat.defaultSize;
        }
        if ("allowedPanels" in config) {
            this.allowedPanelTargets = config.allowedPanels;
        }
        else if (type === WidgetType.ToolSettings)
            this.allowedPanelTargets = [
                StagePanelLocation_1.StagePanelLocation.Bottom,
                StagePanelLocation_1.StagePanelLocation.Left,
                StagePanelLocation_1.StagePanelLocation.Right,
            ];
        if (config.priority !== undefined)
            this._priority = config.priority;
        if (config.tooltip)
            this.setTooltip(config.tooltip);
        else if (config.tooltipKey)
            this._tooltip = UiFramework_1.UiFramework.localization.getLocalizedString(config.tooltipKey);
        if (config.defaultState !== undefined) {
            this._defaultState = config.defaultState;
        }
        this._widgetReactNode = config.content;
        this._icon = config.icon;
        // istanbul ignore next
        if (config.icon !== undefined && this._icon === undefined)
            this._icon = config.icon;
        if (config.badge !== undefined)
            this._badge = config.badge;
        this._preferredPanelSize = config.preferredPanelSize;
    }
    /** @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;
        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 WidgetState_1.WidgetState.Hidden !== this.state;
    }
    get activeState() {
        return this.state;
    }
    get isActive() {
        return WidgetState_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?.length > 0 ? targets : undefined;
    }
    onWidgetStateChanged() {
        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.
     * @public
     */
    show() {
        InternalFrontstageManager_1.InternalFrontstageManager.onWidgetShowEvent.emit({ widgetDef: this });
    }
    /** Opens the widget and expands it to fill full size of the stage panel.
     * @public
     */
    expand() {
        InternalFrontstageManager_1.InternalFrontstageManager.onWidgetExpandEvent.emit({ widgetDef: this });
    }
}
WidgetDef._sId = 0;
exports.WidgetDef = WidgetDef;
//# sourceMappingURL=WidgetDef.js.map