"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 WidgetPanels
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAnimatePanel = void 0;
const React = require("react");
const core_bentley_1 = require("@itwin/core-bentley");
const DragManager_1 = require("../base/DragManager");
const NineZone_1 = require("../base/NineZone");
const LayoutStore_1 = require("../base/LayoutStore");
const Panel_1 = require("./Panel");
/** @internal */
function useAnimatePanel() {
    const side = React.useContext(Panel_1.PanelSideContext);
    (0, core_bentley_1.assert)(!!side);
    const draggedPanelSide = React.useContext(DragManager_1.DraggedPanelSideContext);
    const dispatch = React.useContext(NineZone_1.NineZoneDispatchContext);
    const captured = draggedPanelSide === side;
    const [contentSize, setContentSize] = React.useState();
    const [prepareTransition, setPrepareTransition] = React.useState(false);
    const [transition, setTransition] = React.useState();
    const [panelSize, setPanelSize] = React.useState();
    const [initializing, setInitializing] = React.useState(false);
    const horizontal = (0, Panel_1.isHorizontalPanelSide)(side);
    const animateFrom = React.useRef();
    const animateTo = React.useRef(0);
    const maxPanelSize = React.useRef();
    const collapsing = React.useRef();
    const ref = React.useRef(null);
    const panel = (0, LayoutStore_1.useLayout)((state) => {
        const p = state.panels[side];
        return {
            collapsed: p.collapsed,
            size: p.size,
            minSize: p.minSize,
        };
    }, true);
    const [prevCollapsed, setPrevCollapsed] = React.useState(panel.collapsed);
    if (prevCollapsed !== panel.collapsed) {
        setPrevCollapsed(panel.collapsed);
        let from = animateFrom.current;
        if (from === undefined && ref.current) {
            const bounds = ref.current.getBoundingClientRect();
            from = getPanelSize(horizontal, bounds);
        }
        animateFrom.current = from;
        setPanelSize(undefined);
        setContentSize(undefined);
        setTransition(undefined);
        setPrepareTransition(true);
        if (panel.collapsed) {
            collapsing.current = "collapsing";
            maxPanelSize.current = from;
        }
        else {
            collapsing.current = "expanding";
        }
    }
    const [prevSize, setPrevSize] = React.useState(panel.size);
    if (prevSize !== panel.size) {
        setPrevSize(panel.size);
        if (initializing) {
            // Panel is initializing (via dispatched PANEL_INITIALIZE), need to re-measure animateTo.
            maxPanelSize.current = undefined;
            setPanelSize(undefined);
            setContentSize(undefined);
            setTransition(undefined);
            setPrepareTransition(true);
        }
        else if (collapsing.current === "collapsing") {
            // Panel is collapsing, ignore size changes.
        }
        else if (!captured && ref.current && prevSize !== undefined) {
            // Panel is expanding
            animateFrom.current = getPanelSize(horizontal, ref.current.getBoundingClientRect());
            setPanelSize(undefined);
            setContentSize(undefined);
            setTransition(undefined);
            setPrepareTransition(true);
        }
        else {
            // Panel is resizing, do not transition.
            setPanelSize(undefined);
            setContentSize(undefined);
            setTransition(undefined);
            animateFrom.current = undefined;
            collapsing.current = undefined;
        }
    }
    React.useLayoutEffect(() => {
        if (panel.size !== undefined || panel.collapsed)
            return;
        (0, core_bentley_1.assert)(!!ref.current);
        const bounds = ref.current.getBoundingClientRect();
        const newSize = getPanelSize(horizontal, bounds);
        dispatch({
            type: "PANEL_INITIALIZE",
            side,
            size: newSize,
        });
        setInitializing(true);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [panel.size, panel.collapsed]);
    // eslint-disable-next-line react-hooks/exhaustive-deps
    React.useLayoutEffect(() => {
        if (!prepareTransition)
            return;
        setPrepareTransition(false);
        (0, core_bentley_1.assert)(!!ref.current);
        animateTo.current = getPanelSize(horizontal, ref.current.getBoundingClientRect());
        if (animateFrom.current === animateTo.current) {
            maxPanelSize.current = undefined;
            animateFrom.current = undefined;
            collapsing.current = undefined;
            setPanelSize(undefined);
            setContentSize(undefined);
            setTransition(undefined);
            return;
        }
        if (collapsing.current === "expanding" &&
            maxPanelSize.current === undefined) {
            maxPanelSize.current = animateTo.current;
        }
        setPanelSize(animateFrom.current);
        setContentSize(maxPanelSize.current);
        setTransition("init");
    });
    React.useLayoutEffect(() => {
        if (transition !== "init")
            return;
        const handle = window.requestAnimationFrame(() => {
            animateFrom.current = undefined;
            setTransition("transition");
            setPanelSize(animateTo.current);
        });
        return () => {
            window.cancelAnimationFrame(handle);
        };
    });
    React.useEffect(() => {
        setInitializing(false);
    }, [initializing]);
    const handleTransitionEnd = React.useCallback((e) => {
        if (e.target !== ref.current)
            return;
        maxPanelSize.current = undefined;
        collapsing.current = undefined;
        animateFrom.current = undefined;
        setPanelSize(undefined);
        setContentSize(undefined);
        setTransition(undefined);
    }, []);
    const size = React.useMemo(() => {
        if (panelSize !== undefined)
            return panelSize;
        return panel.collapsed ? 0 : panel.size ?? panel.minSize;
    }, [panel.size, panel.collapsed, panel.minSize, panelSize]);
    return { ref, size, handleTransitionEnd, contentSize, transition };
}
exports.useAnimatePanel = useAnimatePanel;
function getPanelSize(horizontal, size) {
    return horizontal ? size.height : size.width;
}
//# sourceMappingURL=useAnimatePanel.js.map