/*---------------------------------------------------------------------------------------------
* 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 Frontstage
 */
import produce from "immer";
import { StagePanelLocation, StagePanelSection, UiEvent } from "@itwin/appui-abstract";
import { WidgetDef } from "../widgets/WidgetDef";
import { WidgetHost } from "../widgets/WidgetHost";
import { getStableWidgetProps } from "../zones/Zone";
import { UiFramework } from "../UiFramework";
import { InternalFrontstageManager } from "../frontstage/InternalFrontstageManager";
/** Enum for StagePanel state.
 * @public
 */
export var StagePanelState;
(function (StagePanelState) {
    StagePanelState[StagePanelState["Off"] = 0] = "Off";
    StagePanelState[StagePanelState["Minimized"] = 1] = "Minimized";
    StagePanelState[StagePanelState["Open"] = 2] = "Open";
    StagePanelState[StagePanelState["Popup"] = 3] = "Popup";
})(StagePanelState || (StagePanelState = {}));
/** Panel State Changed Event class.
 * @beta
 */
export class PanelStateChangedEvent extends UiEvent {
}
/** @internal */
export class PanelSizeChangedEvent extends UiEvent {
}
/**
 * A StagePanelDef represents each Stage Panel within a Frontstage.
 * @public
 */
export class StagePanelDef extends WidgetHost {
    /** Constructor for PanelDef.
     */
    constructor() {
        super();
        this._panelState = StagePanelState.Open;
        this._defaultState = StagePanelState.Open;
        this._resizable = true;
        this._pinned = true;
        this._location = StagePanelLocation.Left;
        this._panelZones = new StagePanelZonesDef();
    }
    /** @internal */
    get maxSizeSpec() { return this._maxSizeSpec; }
    /** @internal */
    get minSize() { return this._minSize; }
    /** Default size of the panel */
    get size() {
        // istanbul ignore next
        if ("1" === UiFramework.uiVersion)
            return this._size;
        // istanbul ignore else
        if (UiFramework.frontstages.activeFrontstageDef) {
            const [_, size] = UiFramework.frontstages.activeFrontstageDef.getPanelCurrentState(this);
            return size;
        }
        // istanbul ignore next
        return this._defaultSize;
    }
    set size(size) {
        if (this._size === size)
            return;
        // istanbul ignore else
        if (UiFramework.uiVersion === "2") {
            const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
            // istanbul ignore else
            if (frontstageDef && frontstageDef.nineZoneState) {
                const side = toPanelSide(this.location);
                frontstageDef.nineZoneState = setPanelSize(frontstageDef.nineZoneState, side, size);
                const panel = frontstageDef.nineZoneState.panels[side];
                if (panel.size === this._size)
                    return;
                size = panel.size;
            }
        }
        this._size = size;
        InternalFrontstageManager.onPanelSizeChangedEvent.emit({
            panelDef: this,
            size,
        });
    }
    /** Indicates whether the panel is resizable. */
    // istanbul ignore next
    get resizable() { return this._resizable; }
    /** Indicates whether the panel is pinned. */
    get pinned() { return this._pinned; }
    /** Any application data to attach to this Panel. */
    get applicationData() { return this._applicationData; }
    /** Location of panel. */
    get location() { return this._location; }
    /** Panel state. Defaults to PanelState.Open. */
    get panelState() {
        var _a;
        if ("1" === UiFramework.uiVersion)
            return this._panelState;
        // istanbul ignore else
        if (UiFramework.frontstages.activeFrontstageDef) {
            const [state] = (_a = UiFramework.frontstages.activeFrontstageDef) === null || _a === void 0 ? void 0 : _a.getPanelCurrentState(this);
            return state;
        }
        // istanbul ignore next
        return this.defaultState;
    }
    set panelState(panelState) {
        if (panelState === this._panelState)
            return;
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        if (UiFramework.uiVersion === "2" && frontstageDef && frontstageDef.nineZoneState) {
            const side = toPanelSide(this.location);
            frontstageDef.nineZoneState = produce(frontstageDef.nineZoneState, (nineZone) => {
                const panel = nineZone.panels[side];
                switch (panelState) {
                    case StagePanelState.Minimized: {
                        panel.collapsed = true;
                        break;
                    }
                    case StagePanelState.Open: {
                        panel.collapsed = false;
                        break;
                    }
                    case StagePanelState.Off: {
                        panel.collapsed = true;
                        break;
                    }
                }
            });
        }
        this._panelState = panelState;
        UiFramework.frontstages.onPanelStateChangedEvent.emit({
            panelDef: this,
            panelState,
        });
    }
    /** @internal */
    get defaultState() { return this._defaultState; }
    /** @internal */
    get defaultSize() { return this._defaultSize; }
    /** Panel zones.
     * @internal
     */
    get panelZones() {
        return this._panelZones;
    }
    /** @internal */
    initializeFromProps(props, location) {
        if (location !== undefined)
            this._location = location;
        if (!props)
            return;
        this._size = props.size;
        this._defaultSize = props.size;
        this._maxSizeSpec = props.maxSize;
        this._minSize = props.minSize;
        if (props.defaultState !== undefined) {
            this._panelState = props.defaultState;
            this._defaultState = props.defaultState;
        }
        this._resizable = props.resizable;
        if (props.pinned !== undefined)
            this._pinned = props.pinned;
        this._applicationData = props.applicationData;
        if (props.panelZones) {
            this._panelZones.initializeFromProps(props.panelZones, this._location);
        }
        if (props.widgets) {
            props.widgets.forEach((widgetNode, index) => {
                const stableId = `uifw-sp-${StagePanelLocation[this._location]}-${index}`;
                const stableProps = getStableWidgetProps(widgetNode.props, stableId);
                const widgetDef = new WidgetDef(stableProps);
                this.addWidgetDef(widgetDef);
            });
        }
    }
    /** Gets the list of Widgets. */
    get widgetDefs() {
        const widgetDefs = [...super.widgetDefs];
        for (const [, panelZone] of this.panelZones) {
            widgetDefs.push(...panelZone.widgetDefs);
        }
        return widgetDefs;
    }
    /** Gets the list of Widgets (w/o StagePanelZone widgets).
     * @internal
     */
    get panelWidgetDefs() {
        return super.widgetDefs;
    }
    /** @internal */
    updateDynamicWidgetDefs(stageId, stageUsage, location, _section, allStageWidgetDefs, frontstageApplicationData) {
        this.panelZones.start.updateDynamicWidgetDefs(stageId, stageUsage, location, StagePanelSection.Start, allStageWidgetDefs, frontstageApplicationData);
        this.panelZones.end.updateDynamicWidgetDefs(stageId, stageUsage, location, StagePanelSection.Middle, allStageWidgetDefs, frontstageApplicationData);
        this.panelZones.end.updateDynamicWidgetDefs(stageId, stageUsage, location, StagePanelSection.End, allStageWidgetDefs, frontstageApplicationData);
    }
}
const stagePanelZoneDefKeys = ["start", "end"];
/** @internal */
export class StagePanelZonesDef {
    constructor() {
        this._start = new StagePanelZoneDef();
        this._end = new StagePanelZoneDef();
    }
    get start() {
        return this._start;
    }
    get end() {
        return this._end;
    }
    /** @internal */
    initializeFromProps(props, panelLocation) {
        if (props.start) {
            this.start.initializeFromProps(props.start, panelLocation, "start");
        }
        if (props.middle) {
            this.end.initializeFromProps(props.middle, panelLocation, "end");
        }
        if (props.end) {
            this.end.initializeFromProps(props.end, panelLocation, "end");
        }
    }
    /** @internal */
    *[Symbol.iterator]() {
        for (const key of stagePanelZoneDefKeys) {
            const value = this[key];
            yield [key, value];
        }
        return undefined;
    }
}
/** @internal */
export class StagePanelZoneDef extends WidgetHost {
    /** @internal */
    initializeFromProps(props, panelLocation, panelZone) {
        props.widgets.forEach((widgetNode, index) => {
            const stableId = `uifw-spz-${StagePanelLocation[panelLocation]}-${panelZone}-${index}`;
            const stableProps = getStableWidgetProps(widgetNode.props, stableId);
            const widgetDef = new WidgetDef(stableProps);
            this.addWidgetDef(widgetDef);
        });
    }
}
/** @internal */
export function toPanelSide(location) {
    switch (location) {
        case StagePanelLocation.Bottom:
        case StagePanelLocation.BottomMost:
            return "bottom";
        case StagePanelLocation.Left:
            return "left";
        case StagePanelLocation.Right:
            return "right";
        case StagePanelLocation.Top:
        case StagePanelLocation.TopMost:
            return "top";
    }
}
/** @internal */
export const setPanelSize = produce((nineZone, side, size) => {
    const panel = nineZone.panels[side];
    panel.size = size === undefined ? size : Math.min(Math.max(size, panel.minSize), panel.maxSize);
});
//# sourceMappingURL=StagePanelDef.js.map