/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Frontstage
 */
import { UiEvent } from "@itwin/appui-abstract";
import produce from "immer";
import { UiFramework } from "../UiFramework";
import { InternalFrontstageManager } from "../frontstage/InternalFrontstageManager";
import { WidgetDef } from "../widgets/WidgetDef";
import { WidgetHost } from "../widgets/WidgetHost";
import { StagePanelLocation } from "./StagePanelLocation";
import { StagePanelSection } from "./StagePanelSection";
import { StagePanelState } from "./StagePanelState";
/** Panel state changed event class.
 * @beta
 * @deprecated in 4.13.0. This class should not be used by applications to instantiate objects.
 */
// eslint-disable-next-line deprecation/deprecation
export class PanelStateChangedEvent extends UiEvent {
}
/**
 * A StagePanelDef represents each Stage Panel within a Frontstage.
 * @public
 */
export class StagePanelDef extends WidgetHost {
    /** Constructor for PanelDef. */
    constructor() {
        super();
        this._location = StagePanelLocation.Left;
        this._start = new StagePanelSectionDef();
        this._end = new StagePanelSectionDef();
    }
    /** @internal */
    static create(config, location) {
        const def = new StagePanelDef();
        def.initializeFromConfig(config, location);
        return def;
    }
    /** @internal */
    initializeFromConfig(config, location) {
        this._location = location;
        this._initialConfig = config;
        this._start.initializeFromConfig(config?.sections?.start);
        this._end.initializeFromConfig(config?.sections?.end);
    }
    /** @internal */
    get initialConfig() {
        return this._initialConfig;
    }
    /** Current size of the panel.
     * @deprecated in 4.12.0. Use {@link StagePanelDef.sizeSpec} instead.
     */
    get size() {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        const state = frontstageDef?.nineZoneState;
        // eslint-disable-next-line deprecation/deprecation
        if (!state)
            return this.initialConfig?.size;
        const side = toPanelSide(this.location);
        const panel = state.panels[side];
        return panel.size;
    }
    set size(size) {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        if (!frontstageDef)
            return;
        const side = toPanelSide(this.location);
        frontstageDef.dispatch({
            type: "PANEL_SET_SIZE",
            side,
            size,
        });
    }
    /** Current size of the panel */
    get sizeSpec() {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        const state = frontstageDef?.nineZoneState;
        if (!state)
            return this.initialConfig?.sizeSpec;
        const side = toPanelSide(this.location);
        const panel = state.panels[side];
        return panel.size;
    }
    set sizeSpec(size) {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        if (!frontstageDef)
            return;
        const side = toPanelSide(this.location);
        frontstageDef.dispatch({
            type: "PANEL_SET_SIZE",
            side,
            size,
        });
    }
    /** @internal */
    handleSizeChanged(size) {
        InternalFrontstageManager.onPanelSizeChangedEvent.emit({
            panelDef: this,
            size,
        });
    }
    /** Indicates whether the panel is resizable. */
    get resizable() {
        return this.defaultResizable;
    }
    /** Indicates whether the panel is pinned. */
    get pinned() {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        const state = frontstageDef?.nineZoneState;
        if (!state)
            return this.defaultPinned;
        const side = toPanelSide(this.location);
        const panel = state.panels[side];
        return panel.pinned;
    }
    set pinned(pinned) {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        if (!frontstageDef)
            return;
        const side = toPanelSide(this.location);
        frontstageDef.dispatch({
            type: "PANEL_SET_PINNED",
            side,
            pinned,
        });
    }
    /** @internal */
    handlePinnedChanged(pinned) {
        UiFramework.frontstages.onPanelPinnedChangedEvent.emit({
            panelDef: this,
            pinned,
        });
    }
    /** Location of panel. */
    get location() {
        return this._location;
    }
    /** Panel state. Defaults to PanelState.Open. */
    get panelState() {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        const state = frontstageDef?.nineZoneState;
        if (!state)
            return this.defaultState;
        const side = toPanelSide(this.location);
        return getPanelState(state, side);
    }
    set panelState(panelState) {
        const frontstageDef = UiFramework.frontstages.activeFrontstageDef;
        if (!frontstageDef)
            return;
        const side = toPanelSide(this.location);
        const collapsed = panelState === StagePanelState.Open ? false : true;
        frontstageDef.dispatch({
            type: "PANEL_SET_COLLAPSED",
            collapsed,
            side,
        });
    }
    /** @internal */
    handlePanelStateChanged(panelState) {
        UiFramework.frontstages.onPanelStateChangedEvent.emit({
            panelDef: this,
            panelState,
        });
    }
    /** @internal */
    get defaultState() {
        const defaultState = this._initialConfig?.defaultState;
        return defaultState ?? StagePanelState.Open;
    }
    /** @internal */
    get defaultPinned() {
        return this._initialConfig?.pinned ?? true;
    }
    /** @internal */
    get defaultResizable() {
        return this._initialConfig?.resizable ?? true;
    }
    /** Gets the list of Widgets. */
    get widgetDefs() {
        return [
            ...super.widgetDefs,
            ...this._start.widgetDefs,
            ...this._end.widgetDefs,
        ];
    }
    /** @internal */
    updateDynamicWidgetDefs(stageId, stageUsage, location, _section, allStageWidgetDefs) {
        this._start.updateDynamicWidgetDefs(stageId, stageUsage, location, StagePanelSection.Start, allStageWidgetDefs);
        this._end.updateDynamicWidgetDefs(stageId, stageUsage, location, StagePanelSection.End, allStageWidgetDefs);
    }
    /** @internal */
    getPanelSectionDef(section) {
        switch (section) {
            case StagePanelSection.Start: {
                return this._start;
            }
            case StagePanelSection.End: {
                return this._end;
            }
        }
    }
}
/** @internal */
export class StagePanelSectionDef extends WidgetHost {
    /** @internal */
    initializeFromConfig(config) {
        config?.forEach((widgetConfig) => {
            const widgetDef = WidgetDef.create(widgetConfig);
            this.addWidgetDef(widgetDef);
        });
    }
}
/** @internal */
export function toPanelSide(location) {
    switch (location) {
        case StagePanelLocation.Bottom:
            return "bottom";
        case StagePanelLocation.Left:
            return "left";
        case StagePanelLocation.Right:
            return "right";
        case StagePanelLocation.Top:
            return "top";
    }
}
/** @internal */
export const setPanelPinned = produce((nineZone, side, pinned) => {
    const panel = nineZone.panels[side];
    panel.pinned = pinned;
});
/** @internal */
export function getPanelState(state, side) {
    const panel = state.panels[side];
    return panel.collapsed ? StagePanelState.Minimized : StagePanelState.Open;
}
//# sourceMappingURL=StagePanelDef.js.map