"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.useActiveTabId = exports.restrainInitialWidgetSize = exports.WidgetContext = exports.WidgetIdContext = exports.Widget = exports.WidgetProvider = void 0;
require("./Widget.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("../widget-panels/Panel");
const LayoutStore_1 = require("../base/LayoutStore");
const WidgetStateHelpers_1 = require("../state/internal/WidgetStateHelpers");
const FloatingWidget_1 = require("./FloatingWidget");
/** @internal */
function WidgetProvider(props) {
    return (React.createElement(exports.WidgetIdContext.Provider, { value: props.id }, props.children));
}
exports.WidgetProvider = WidgetProvider;
/** @internal */
exports.Widget = React.forwardRef(function Widget(props, forwardedRef) {
    const dispatch = React.useContext(NineZone_1.NineZoneDispatchContext);
    const side = React.useContext(Panel_1.PanelSideContext);
    const id = React.useContext(exports.WidgetIdContext);
    const measureNz = React.useContext(NineZone_1.MeasureContext);
    const floatingWidgetId = (0, FloatingWidget_1.useFloatingWidgetId)();
    (0, core_bentley_1.assert)(!!id);
    const { preferredFloatingWidgetSize, userSized } = (0, LayoutStore_1.useLayout)((state) => {
        const widget = (0, WidgetStateHelpers_1.getWidgetState)(state, id);
        const tab = state.tabs[widget.activeTabId];
        return {
            preferredFloatingWidgetSize: tab.preferredFloatingWidgetSize,
            userSized: tab.userSized ||
                (tab.isFloatingWidgetResizable && !!tab.preferredFloatingWidgetSize),
        };
    }, true);
    const elementRef = React.useRef(null);
    const widgetId = floatingWidgetId === undefined ? id : floatingWidgetId;
    const onDragStart = React.useCallback((updateId, initialPointerPosition, pointerPosition) => {
        (0, core_bentley_1.assert)(!!elementRef.current);
        if (floatingWidgetId !== undefined)
            return;
        const nzBounds = measureNz();
        let bounds = core_react_1.Rectangle.create(elementRef.current.getBoundingClientRect());
        const size = restrainInitialWidgetSize(bounds.getSize(), nzBounds.getSize());
        bounds = bounds.setSize(size);
        if (preferredFloatingWidgetSize) {
            bounds = bounds.setSize(preferredFloatingWidgetSize);
        }
        // Pointer is outside of tab area. Need to re-adjust widget bounds so that tab is behind pointer
        if (initialPointerPosition.x > bounds.right) {
            const offset = initialPointerPosition.x - bounds.right + 20;
            bounds = bounds.offsetX(offset);
        }
        const dragOffset = initialPointerPosition.getOffsetTo(pointerPosition);
        bounds = bounds.offset(dragOffset);
        // Adjust bounds to be relative to 9z origin
        bounds = bounds.offset({ x: -nzBounds.left, y: -nzBounds.top });
        const newFloatingWidgetId = (0, NineZone_1.getUniqueId)();
        updateId(newFloatingWidgetId);
        (0, core_bentley_1.assert)(!!side);
        dispatch({
            type: "PANEL_WIDGET_DRAG_START",
            newFloatingWidgetId,
            id,
            bounds,
            side,
            userSized,
        });
    }, [
        dispatch,
        floatingWidgetId,
        id,
        side,
        measureNz,
        preferredFloatingWidgetSize,
        userSized,
    ]);
    (0, DragManager_1.useDragWidget)({
        widgetId,
        onDragStart,
    });
    React.useEffect(() => {
        const listener = () => {
            floatingWidgetId &&
                dispatch({
                    type: "FLOATING_WIDGET_BRING_TO_FRONT",
                    id: floatingWidgetId,
                });
        };
        const element = elementRef.current;
        element?.addEventListener("click", listener);
        return () => {
            element?.removeEventListener("click", listener);
        };
    }, [dispatch, floatingWidgetId]);
    const measure = React.useCallback(() => {
        if (!elementRef.current)
            return new core_react_1.Rectangle();
        const bounds = elementRef.current.getBoundingClientRect();
        return core_react_1.Rectangle.create(bounds);
    }, []);
    const widgetContextValue = React.useMemo(() => ({
        measure,
    }), [measure]);
    const ref = (0, core_react_1.useRefs)(forwardedRef, elementRef);
    const className = (0, classnames_1.default)("nz-widget-widget", props.className);
    return (React.createElement(exports.WidgetContext.Provider, { value: widgetContextValue },
        React.createElement("div", { className: className, onMouseEnter: props.onMouseEnter, onMouseLeave: props.onMouseLeave, onTransitionEnd: props.onTransitionEnd, ref: ref, style: props.style, "data-widget-id": props.widgetId }, props.children)));
});
/** @internal */
exports.WidgetIdContext = React.createContext(undefined);
exports.WidgetIdContext.displayName = "nz:WidgetIdContext";
/** @internal */
exports.WidgetContext = React.createContext(null);
exports.WidgetContext.displayName = "nz:WidgetContext";
const minWidth = 200;
const minHeight = 200;
/** @internal */
function restrainInitialWidgetSize(size, nzSize) {
    const width = Math.max(Math.min(nzSize.width / 3, size.width), minWidth);
    const height = Math.max(Math.min(nzSize.height / 3, size.height), minHeight);
    return {
        width,
        height,
    };
}
exports.restrainInitialWidgetSize = restrainInitialWidgetSize;
/** @internal */
function useActiveTabId() {
    const id = React.useContext(exports.WidgetIdContext);
    (0, core_bentley_1.assert)(!!id);
    return (0, LayoutStore_1.useLayout)((state) => {
        const widget = (0, WidgetStateHelpers_1.getWidgetState)(state, id);
        return widget.activeTabId;
    });
}
exports.useActiveTabId = useActiveTabId;
//# sourceMappingURL=Widget.js.map