/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Base
 */
import * as React from "react";
import { assert, Guid } from "@itwin/core-bentley";
import { Rectangle, useRefs, useResizeObserver, } from "@itwin/core-react/internal";
import { WidgetContentManager } from "../widget/ContentManager.js";
import { FloatingWidget } from "../widget/FloatingWidget.js";
import { DraggedPanelSideContext, DraggedResizeHandleContext, DraggedWidgetIdContext, DragProvider, } from "./DragManager.js";
import { ShowActiveWidgetLabelContext, WidgetTab } from "../widget/Tab.js";
import { LayoutStoreContext, useLayout } from "./LayoutStore.js";
/** @internal */
export function NineZone(props) {
    const { children, ...providerProps } = props;
    const measurerRef = React.useRef(null);
    const measure = React.useCallback(() => {
        assert(!!measurerRef.current);
        return Rectangle.create(measurerRef.current.getBoundingClientRect());
    }, []);
    return (React.createElement(NineZoneProvider, { measure: measure, ...providerProps },
        React.createElement(Measurer, { ref: measurerRef }),
        children));
}
const tab = React.createElement(WidgetTab, null);
const floatingWidget = React.createElement(FloatingWidget, null);
/** @internal */
export function NineZoneProvider(props) {
    return (React.createElement(LayoutStoreContext.Provider, { value: props.layout },
        React.createElement(NineZoneDispatchContext.Provider, { value: props.dispatch },
            React.createElement(NineZoneLabelsContext.Provider, { value: props.labels },
                React.createElement(UiIsVisibleContext.Provider, { value: !!props.uiIsVisible },
                    React.createElement(ShowActiveWidgetLabelContext.Provider, { value: !!props.showActiveWidgetLabel },
                        React.createElement(ShowWidgetIconContext.Provider, { value: !!props.showWidgetIcon },
                            React.createElement(AutoCollapseUnpinnedPanelsContext.Provider, { value: !!props.autoCollapseUnpinnedPanels },
                                React.createElement(WidgetContentNodeContext.Provider, { value: props.widgetContent },
                                    React.createElement(ToolSettingsNodeContext.Provider, { value: props.toolSettingsContent },
                                        React.createElement(TabNodeContext.Provider, { value: props.tab || tab },
                                            React.createElement(FloatingWidgetNodeContext.Provider, { value: props.floatingWidget || floatingWidget },
                                                React.createElement(AnimateDockedToolSettingsContext.Provider, { value: !!props.animateDockedToolSettings },
                                                    React.createElement(DragProvider, null,
                                                        React.createElement(CursorTypeProvider, null,
                                                            React.createElement(WidgetContentManager, null,
                                                                React.createElement(MeasureContext.Provider, { value: props.measure }, props.children)))))))))))))))));
}
/** @internal */
export const NineZoneDispatchContext = React.createContext(null);
NineZoneDispatchContext.displayName = "nz:NineZoneDispatchContext";
/** @internal */
export const NineZoneLabelsContext = React.createContext(undefined);
NineZoneLabelsContext.displayName = "nz:NineZoneLabelsContext";
/** @internal */
export const CursorTypeContext = React.createContext(undefined);
CursorTypeContext.displayName = "nz:CursorTypeContext";
/** @internal */
export const WidgetContentNodeContext = React.createContext(undefined);
WidgetContentNodeContext.displayName = "nz:WidgetContentNodeContext";
/** @internal */
export const ShowWidgetIconContext = React.createContext(false);
ShowWidgetIconContext.displayName = "nz:ShowWidgetIconContext";
/** @internal */
export const AutoCollapseUnpinnedPanelsContext = React.createContext(false);
AutoCollapseUnpinnedPanelsContext.displayName =
    "nz:AutoCollapseUnpinnedPanelsContext";
/** @internal */
export const AnimateDockedToolSettingsContext = React.createContext(false);
AnimateDockedToolSettingsContext.displayName =
    "nz:AnimateDockedToolSettingsContext";
/** @internal */
export const ToolSettingsNodeContext = React.createContext(undefined);
ToolSettingsNodeContext.displayName = "nz:ToolSettingsNodeContext";
/** @internal */
export const TabNodeContext = React.createContext(undefined);
TabNodeContext.displayName = "nz:TabNodeContext";
/** @internal */
export const FloatingWidgetNodeContext = React.createContext(undefined);
FloatingWidgetNodeContext.displayName = "nz:FloatingWidgetNodeContext";
/** @internal */
export const MeasureContext = React.createContext(null);
MeasureContext.displayName = "nz:MeasureContext";
/** @internal */
export const UiIsVisibleContext = React.createContext(false);
UiIsVisibleContext.displayName = "nz:UiIsVisibleContext";
function CursorTypeProvider(props) {
    const draggedTab = useLayout((state) => !!state.draggedTab);
    const draggedWidgetId = React.useContext(DraggedWidgetIdContext);
    const draggedPanelSide = React.useContext(DraggedPanelSideContext);
    const draggedResizeHandle = React.useContext(DraggedResizeHandleContext);
    let type;
    if (draggedTab || draggedWidgetId)
        type = "grabbing";
    else if (draggedPanelSide)
        type = sideToCursorType(draggedPanelSide);
    else if (draggedResizeHandle)
        type = handleToCursorType(draggedResizeHandle);
    return (React.createElement(CursorTypeContext.Provider, { value: type }, props.children));
}
const Measurer = React.forwardRef(function Measurer(_, ref) {
    const size = React.useRef({});
    const dispatch = React.useContext(NineZoneDispatchContext);
    const handleResize = React.useCallback((width, height) => {
        if (size.current.width === width && size.current.height === height)
            return;
        size.current.height = height;
        size.current.width = width;
        dispatch({
            type: "RESIZE",
            size: {
                height,
                width,
            },
        });
    }, [dispatch]);
    const roRef = useResizeObserver(handleResize);
    const refs = useRefs(ref, roRef);
    return (React.createElement("div", { ref: refs, style: {
            position: "absolute",
            width: "100%",
            height: "100%",
            top: "0",
            left: "0",
            visibility: "hidden",
        } }));
});
/** @internal */
export function sideToCursorType(side) {
    switch (side) {
        case "bottom":
        case "top":
            return "ns-resize";
        case "left":
        case "right":
            return "ew-resize";
    }
}
/** @internal */
export function handleToCursorType(handle) {
    switch (handle) {
        case "bottom":
        case "top":
            return "ns-resize";
        case "left":
        case "right":
            return "ew-resize";
        case "topLeft":
        case "bottomRight":
            return "nwse-resize";
        case "topRight":
        case "bottomLeft":
            return "nesw-resize";
    }
}
/** @internal */
export function getUniqueId() {
    return Guid.createValue();
}
/** @internal */
export function useLabel(labelKey) {
    const labels = React.useContext(NineZoneLabelsContext);
    return labels?.[labelKey];
}
//# sourceMappingURL=NineZone.js.map