"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.IconOnlyOnWidgetTabContext = exports.TabPositionContext = exports.useTabInteractions = exports.WidgetTab = exports.WidgetTabProvider = void 0;
require("./Tab.scss");
const classnames_1 = require("classnames");
const React = require("react");
const ts_key_enum_1 = require("ts-key-enum");
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 usePointerCaptor_1 = require("../base/usePointerCaptor");
const Panel_1 = require("../widget-panels/Panel");
const Tabs_1 = require("./Tabs");
const Widget_1 = require("./Widget");
const ContentRenderer_1 = require("./ContentRenderer");
const TabTarget_1 = require("../target/TabTarget");
const MenuTab_1 = require("./MenuTab");
const Overflow_1 = require("./Overflow");
const LayoutStore_1 = require("../base/LayoutStore");
const FloatingWidget_1 = require("./FloatingWidget");
const WidgetStateHelpers_1 = require("../state/internal/WidgetStateHelpers");
const useMaximizedWidget_1 = require("../../preview/enable-maximized-widget/useMaximizedWidget");
/** @internal */
function WidgetTabProvider({ id, first, firstInactive, last, showOnlyTabIcon, }) {
    const tabNode = React.useContext(NineZone_1.TabNodeContext);
    const position = React.useMemo(() => ({
        first,
        firstInactive,
        last,
    }), [first, firstInactive, last]);
    return (React.createElement(ContentRenderer_1.TabIdContext.Provider, { value: id },
        React.createElement(exports.TabPositionContext.Provider, { value: position },
            React.createElement(exports.IconOnlyOnWidgetTabContext.Provider, { value: !!showOnlyTabIcon }, tabNode))));
}
exports.WidgetTabProvider = WidgetTabProvider;
/** Component that displays a tab in a side panel widget.
 * @internal
 */
function WidgetTab(props) {
    const widgetOverflow = React.useContext(Overflow_1.WidgetOverflowContext);
    const overflown = !!widgetOverflow;
    if (overflown)
        return React.createElement(MenuTab_1.WidgetMenuTab, { ...props });
    return React.createElement(WidgetTabComponent, { ...props });
}
exports.WidgetTab = WidgetTab;
function WidgetTabComponent(props) {
    const id = React.useContext(ContentRenderer_1.TabIdContext);
    const { first, firstInactive, last } = React.useContext(exports.TabPositionContext);
    const widgetTabsEntryContext = React.useContext(Tabs_1.WidgetTabsEntryContext);
    const side = React.useContext(Panel_1.PanelSideContext);
    const widgetId = React.useContext(Widget_1.WidgetIdContext);
    const showIconOnly = React.useContext(exports.IconOnlyOnWidgetTabContext);
    const showWidgetIcon = React.useContext(NineZone_1.ShowWidgetIconContext);
    (0, core_bentley_1.assert)(!!id);
    (0, core_bentley_1.assert)(!!widgetId);
    const iconSpec = (0, LayoutStore_1.useLayout)((state) => state.tabs[id].iconSpec);
    const label = (0, LayoutStore_1.useLayout)((state) => state.tabs[id].label);
    const activeTabId = (0, LayoutStore_1.useLayout)((state) => (0, WidgetStateHelpers_1.getWidgetState)(state, widgetId).activeTabId);
    const minimized = (0, LayoutStore_1.useLayout)((state) => (0, WidgetStateHelpers_1.getWidgetState)(state, widgetId).minimized);
    const maximizedWidget = (0, useMaximizedWidget_1.useIsMaximizedWidget)();
    const resizeObserverRef = (0, core_react_1.useResizeObserver)(widgetTabsEntryContext?.onResize);
    const pointerCaptorRef = useTabInteractions({ clickOnly: maximizedWidget });
    const refs = (0, core_react_1.useRefs)(resizeObserverRef, pointerCaptorRef);
    const active = activeTabId === id;
    const className = (0, classnames_1.default)("nz-widget-tab", active && "nz-active", undefined === side && minimized && "nz-minimized", first && "nz-first", last && "nz-last", firstInactive && "nz-first-inactive", props.className);
    const showLabel = (showIconOnly && !iconSpec) ||
        (showWidgetIcon && !showIconOnly) ||
        !showWidgetIcon;
    return (React.createElement("div", { "data-item-id": id, "data-item-type": "widget-tab", className: className, ref: refs, role: "tab", style: props.style, title: label, tabIndex: 0 },
        (showWidgetIcon || showIconOnly) && iconSpec && (React.createElement(core_react_1.Icon, { iconSpec: iconSpec })),
        showLabel && React.createElement("span", null, label),
        props.badge && React.createElement("div", { className: "nz-badge" }, props.badge),
        React.createElement(TabTarget_1.TabTarget, null)));
}
/** @internal */
function useTabInteractions({ onClick, onDoubleClick, onDragStart, clickOnly, }) {
    const id = React.useContext(ContentRenderer_1.TabIdContext);
    const widgetContext = React.useContext(Widget_1.WidgetContext);
    const measure = React.useContext(NineZone_1.MeasureContext);
    const dispatch = React.useContext(NineZone_1.NineZoneDispatchContext);
    const side = React.useContext(Panel_1.PanelSideContext);
    const widgetId = React.useContext(Widget_1.WidgetIdContext);
    const widgetTabsEntryContext = React.useContext(Tabs_1.WidgetTabsEntryContext);
    const floatingWidgetId = (0, FloatingWidget_1.useFloatingWidgetId)();
    (0, core_bentley_1.assert)(!!id);
    (0, core_bentley_1.assert)(!!widgetId);
    const layoutStore = (0, LayoutStore_1.useLayoutStore)();
    const tabRef = React.useRef(layoutStore.getState().tabs[id]);
    const clickCount = React.useRef(0);
    // eslint-disable-next-line deprecation/deprecation
    const doubleClickTimer = React.useRef(new core_react_1.Timer(300));
    const initialPointerPosition = React.useRef();
    const overflown = !widgetTabsEntryContext;
    React.useEffect(() => layoutStore.subscribe((state) => {
        tabRef.current = state.tabs[id];
    }), [layoutStore, id]);
    const handleClick = React.useCallback(() => {
        dispatch({
            type: "WIDGET_TAB_CLICK",
            side,
            widgetId,
            id,
        });
        onClick?.();
    }, [dispatch, widgetId, id, side, onClick]);
    const handleDoubleClick = React.useCallback(() => {
        if (clickOnly)
            return;
        dispatch({
            type: "WIDGET_TAB_DOUBLE_CLICK",
            side,
            widgetId,
            floatingWidgetId,
            id,
        });
        onDoubleClick?.();
    }, [
        clickOnly,
        dispatch,
        floatingWidgetId,
        widgetId,
        id,
        side,
        onDoubleClick,
    ]);
    const handleDragTabStart = (0, DragManager_1.useDragTab)({
        tabId: id,
    });
    const handleDragStart = React.useCallback((pointerPosition) => {
        if (clickOnly)
            return;
        (0, core_bentley_1.assert)(!!ref.current);
        (0, core_bentley_1.assert)(!!initialPointerPosition.current);
        const nzBounds = measure();
        const nzOffset = new core_react_1.Point(-nzBounds.left, -nzBounds.top);
        let bounds = core_react_1.Rectangle.create(ref.current.getBoundingClientRect());
        bounds = bounds.offset(nzOffset);
        const tab = tabRef.current;
        const userSized = tab.userSized ||
            (tab.isFloatingWidgetResizable && !!tab.preferredFloatingWidgetSize);
        let position = bounds.topLeft();
        const widgetBounds = widgetContext.measure();
        const widgetSize = (0, Widget_1.restrainInitialWidgetSize)(widgetBounds.getSize(), nzBounds.getSize());
        if (overflown) {
            position = initialPointerPosition.current.offset(nzOffset);
            position = position.offset({ x: -7, y: -7 });
        }
        const dragOffset = initialPointerPosition.current.getOffsetTo(pointerPosition);
        position = position.offset(dragOffset);
        handleDragTabStart({
            initialPointerPosition: core_react_1.Point.create(initialPointerPosition.current),
            pointerPosition,
            widgetSize,
        });
        dispatch({
            type: "WIDGET_TAB_DRAG_START",
            floatingWidgetId,
            side,
            widgetId,
            id,
            position,
            userSized,
        });
        onDragStart?.();
        initialPointerPosition.current = undefined;
    }, [
        clickOnly,
        measure,
        widgetContext,
        handleDragTabStart,
        dispatch,
        floatingWidgetId,
        side,
        widgetId,
        id,
        onDragStart,
        overflown,
    ]);
    const handlePointerDown = React.useCallback((args, e) => {
        e.type === "touchstart" &&
            floatingWidgetId &&
            dispatch({
                type: "FLOATING_WIDGET_BRING_TO_FRONT",
                id: floatingWidgetId,
            });
        initialPointerPosition.current = new core_react_1.Point(args.clientX, args.clientY);
    }, [dispatch, floatingWidgetId]);
    const handlePointerMove = React.useCallback((args) => {
        if (!initialPointerPosition.current)
            return;
        const pointerPosition = new core_react_1.Point(args.clientX, args.clientY);
        const distance = initialPointerPosition.current.getDistanceTo(pointerPosition);
        if (distance < 10)
            return;
        handleDragStart(pointerPosition);
    }, [handleDragStart]);
    const handlePointerUp = React.useCallback(() => {
        clickCount.current++;
        initialPointerPosition.current = undefined;
        doubleClickTimer.current.start();
    }, []);
    const pointerCaptorRef = (0, usePointerCaptor_1.usePointerCaptor)(handlePointerDown, handlePointerMove, handlePointerUp);
    const ref = React.useRef();
    const refs = (0, core_react_1.useRefs)(pointerCaptorRef, ref);
    React.useEffect(() => {
        const timer = doubleClickTimer.current;
        timer.setOnExecute(() => {
            if (clickCount.current === 1)
                handleClick();
            else
                handleDoubleClick();
            clickCount.current = 0;
        });
        const keydown = (e) => {
            if (e.key === " " || e.key === ts_key_enum_1.Key.Enter.valueOf()) {
                handleClick();
            }
        };
        const instance = ref.current;
        instance && instance.addEventListener("keydown", keydown);
        return () => {
            timer.setOnExecute(undefined);
            instance && instance.removeEventListener("keydown", keydown);
        };
    }, [handleClick, handleDoubleClick]);
    return refs;
}
exports.useTabInteractions = useTabInteractions;
/** @internal */
exports.TabPositionContext = React.createContext(undefined);
exports.TabPositionContext.displayName = "nz:TabPositionContext";
/** @internal */
exports.IconOnlyOnWidgetTabContext = React.createContext(false);
exports.IconOnlyOnWidgetTabContext.displayName = "nz:IconOnlyOnWidgetTabContext";
//# sourceMappingURL=Tab.js.map