"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.useDoubleClick = exports.useResizeGrip = exports.WidgetPanelGrip = void 0;
require("./Grip.scss");
const classnames_1 = require("classnames");
const React = require("react");
const core_bentley_1 = require("@itwin/core-bentley");
const core_react_1 = require("@itwin/core-react");
const DragManager_1 = require("../base/DragManager");
const NineZone_1 = require("../base/NineZone");
const Panel_1 = require("./Panel");
const usePointerCaptor_1 = require("../base/usePointerCaptor");
const LayoutStore_1 = require("../base/LayoutStore");
const useMaximizedWidget_1 = require("../../preview/enable-maximized-widget/useMaximizedWidget");
/** Resize grip of [[WidgetPanel]] component.
 * @internal
 */
// eslint-disable-next-line deprecation/deprecation
function WidgetPanelGrip(props) {
    const side = React.useContext(Panel_1.PanelSideContext);
    (0, core_bentley_1.assert)(!!side);
    const { collapsed, pinned } = (0, LayoutStore_1.useLayout)((state) => {
        const panel = state.panels[side];
        return {
            collapsed: panel.collapsed,
            pinned: panel.pinned,
        };
    }, true);
    const dispatch = React.useContext(NineZone_1.NineZoneDispatchContext);
    const [ref, resizing, active] = (0, exports.useResizeGrip)();
    const className = (0, classnames_1.default)("nz-widgetPanels-grip", `nz-${side}`, active && "nz-active", resizing && "nz-resizing", props.className);
    const resizeGripTitle = (0, NineZone_1.useLabel)("resizeGripTitle");
    const isMaximizedPanel = !!(0, useMaximizedWidget_1.useMaximizedPanel)(side);
    if (isMaximizedPanel)
        return null;
    return (React.createElement("div", { className: className, title: resizeGripTitle, style: props.style },
        React.createElement("div", { className: "nz-line-grip" },
            React.createElement("div", { className: "nz-line-grip-detail" })),
        React.createElement("div", { className: "nz-handle", ref: ref, onMouseOverCapture: () => {
                collapsed &&
                    !pinned &&
                    !resizing &&
                    dispatch({
                        side,
                        collapsed: false,
                        type: "PANEL_SET_COLLAPSED",
                    });
            } })));
}
exports.WidgetPanelGrip = WidgetPanelGrip;
/** @internal */
const useResizeGrip = () => {
    const widgetPanel = React.useContext(Panel_1.WidgetPanelContext);
    const side = React.useContext(Panel_1.PanelSideContext);
    const dispatch = React.useContext(NineZone_1.NineZoneDispatchContext);
    (0, core_bentley_1.assert)(!!side);
    (0, core_bentley_1.assert)(!!widgetPanel);
    const [resizing, setResizing] = React.useState(false);
    const [active, setActive] = React.useState(false);
    const initialPointerPosition = React.useRef();
    // eslint-disable-next-line deprecation/deprecation
    const dragStartTimer = React.useRef(new core_react_1.Timer(300));
    const ref = React.useRef(null);
    const relativePosition = React.useRef(new core_react_1.Point());
    const layoutStore = (0, LayoutStore_1.useLayoutStore)();
    const panelStateRef = React.useRef(layoutStore.getState().panels[side]);
    React.useLayoutEffect(() => layoutStore.subscribe((state) => {
        panelStateRef.current = state.panels[side];
    }), [layoutStore, side]);
    const handleDoubleClick = React.useCallback(() => {
        dispatch({
            type: "PANEL_TOGGLE_COLLAPSED",
            side,
        });
    }, [dispatch, side]);
    const handleClick = useDoubleClick(handleDoubleClick);
    const onDrag = React.useCallback((pointerPosition, lastPointerPosition) => {
        if (!ref.current)
            return;
        const direction = side === "left" || side === "top" ? 1 : -1;
        const dragOffset = lastPointerPosition.getOffsetTo(pointerPosition);
        const dragBy = (0, Panel_1.isHorizontalPanelSide)(side) ? dragOffset.y : dragOffset.x;
        const resizeBy = direction * dragBy;
        const bounds = widgetPanel.getBounds();
        const outerEdge = bounds[side];
        const innerEdge = (0, Panel_1.isHorizontalPanelSide)(side)
            ? pointerPosition.y
            : pointerPosition.x;
        const size = (innerEdge - outerEdge) * direction;
        const panel = panelStateRef.current;
        if (resizeBy === 0)
            return;
        if (panel.collapsed) {
            if (size >= panel.collapseOffset) {
                dispatch({
                    type: "PANEL_SET_COLLAPSED",
                    side,
                    collapsed: false,
                });
                return;
            }
            return;
        }
        if (panel.size === undefined)
            return;
        // New size should match drag direction (i.e. dragging `left` panel grip to the left should not increase left panel size).
        const sizeDiff = size - panel.size;
        if (sizeDiff * resizeBy < 0)
            return;
        const collapseThreshold = Math.max(panel.minSize - panel.collapseOffset, 0);
        if (size <= collapseThreshold) {
            dispatch({
                type: "PANEL_SET_COLLAPSED",
                side,
                collapsed: true,
            });
            dispatch({
                type: "PANEL_SET_SIZE",
                side,
                size: panel.minSize,
            });
            return;
        }
        dispatch({
            type: "PANEL_SET_SIZE",
            side,
            size,
        });
    }, [dispatch, side, widgetPanel]);
    const onDragEnd = React.useCallback(() => {
        setResizing(false);
    }, []);
    const handlePanelGripDragStart = (0, DragManager_1.useDragPanelGrip)({
        side,
        onDrag,
        onDragEnd,
    });
    React.useEffect(() => {
        const timer = dragStartTimer.current;
        timer.setOnExecute(() => {
            if (initialPointerPosition.current && ref.current) {
                relativePosition.current = core_react_1.Rectangle.create(ref.current.getBoundingClientRect())
                    .topLeft()
                    .getOffsetTo(initialPointerPosition.current);
                setResizing(true);
                handlePanelGripDragStart({
                    initialPointerPosition: initialPointerPosition.current,
                    pointerPosition: initialPointerPosition.current,
                });
            }
            initialPointerPosition.current = undefined;
        });
        return () => {
            timer.setOnExecute(undefined);
        };
    }, [handlePanelGripDragStart]);
    const handleDragEnd = React.useCallback(() => {
        initialPointerPosition.current = undefined;
        dragStartTimer.current.stop();
        handleClick();
        setActive(false);
    }, [handleClick]);
    const handlePointerDown = React.useCallback((args) => {
        initialPointerPosition.current = new core_react_1.Point(args.clientX, args.clientY);
        dragStartTimer.current.start();
        setActive(true);
    }, []);
    const handlePointerMove = React.useCallback((args) => {
        if (!initialPointerPosition.current)
            return;
        const position = new core_react_1.Point(args.clientX, args.clientY);
        setResizing(true);
        handlePanelGripDragStart({
            initialPointerPosition: position,
            pointerPosition: position,
        });
        onDrag(position, initialPointerPosition.current);
        initialPointerPosition.current = undefined;
        dragStartTimer.current.stop();
    }, [handlePanelGripDragStart, onDrag]);
    const handlePointerCaptorRef = (0, usePointerCaptor_1.usePointerCaptor)(handlePointerDown, handlePointerMove, handleDragEnd);
    const handleRef = React.useCallback((instance) => {
        ref.current = instance;
        handlePointerCaptorRef(instance);
    }, [handlePointerCaptorRef]);
    return [handleRef, resizing, active];
};
exports.useResizeGrip = useResizeGrip;
/** @internal */
function useDoubleClick(onDoubleClick) {
    // eslint-disable-next-line deprecation/deprecation
    const timer = React.useRef(new core_react_1.Timer(300));
    const clickCount = React.useRef(0);
    timer.current.setOnExecute(() => {
        clickCount.current = 0;
    });
    const handleClick = React.useCallback(() => {
        timer.current.start();
        clickCount.current++;
        if (clickCount.current === 2) {
            onDoubleClick && onDoubleClick();
            clickCount.current = 0;
            timer.current.stop();
        }
    }, [onDoubleClick]);
    return handleClick;
}
exports.useDoubleClick = useDoubleClick;
//# sourceMappingURL=Grip.js.map