/* @oracle/oraclejet-preact: undefined */
import { jsxs, Fragment, jsx } from 'preact/jsx-runtime';
import { useRef, useState } from 'preact/hooks';
import { i as isTouch } from './clientUtils-0df8cb15.js';
import { u as useVisDragModeControls } from './useVisDragModeControls-ed260d12.js';
import { styles } from './hooks/PRIVATE_useChartMarquee/themes/useChartMarquee.css.js';

/**
 * @license
 * Copyright (c) %FIRST_YEAR% %CURRENT_YEAR%, Oracle and/or its affiliates.
 * Licensed under The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 * @ignore
 */
function getResolvedDragMode(isUserDragModeButtonShown, isZoomAndScroll, isMobile, dragMode, userSelectedDragMode, isMultiSelection) {
    if (userSelectedDragMode != undefined && isUserDragModeButtonShown) {
        // when dragMode api value change happens, userDragMode state can be stale.
        // only select userDragMode if there is a button that is present to select it.
        return userSelectedDragMode;
    }
    if (dragMode === 'user') {
        if (!isMobile) {
            return isZoomAndScroll ? 'pan' : isMultiSelection ? 'select' : 'off';
        }
    }
    return isMobile ? 'off' : dragMode;
}
function getMarqueeDims(initialPoint, finalPoint, plotAreaSpace, xSpace, ySpace, treatAsXSpace) {
    if (initialPoint && finalPoint) {
        const spaceWidth = plotAreaSpace.x + plotAreaSpace.width;
        const spaceHeight = plotAreaSpace.y + plotAreaSpace.height;
        let x1 = Math.max(Math.min(initialPoint.x, finalPoint.x), plotAreaSpace.x);
        let x2 = Math.min(Math.max(initialPoint.x, finalPoint.x), spaceWidth);
        let y1 = Math.max(Math.min(initialPoint.y, finalPoint.y), plotAreaSpace.y);
        const y2 = Math.min(Math.max(initialPoint.y, finalPoint.y), spaceHeight);
        let width = Math.abs(x2 - x1);
        let height = Math.abs(y2 - y1);
        if (isPointInsideSpace(initialPoint.x, initialPoint.y, xSpace) || treatAsXSpace) {
            y1 = plotAreaSpace.y;
            height = plotAreaSpace.height;
        }
        else if (isPointInsideSpace(initialPoint.x, initialPoint.y, ySpace)) {
            x1 = plotAreaSpace.x;
            x2 = spaceWidth;
            width = plotAreaSpace.width;
        }
        return {
            x1,
            y1,
            width,
            height,
            x2,
            y2
        };
    }
    return;
}
function getCursorType(currentDragMode, isPointerDown) {
    if (currentDragMode === 'zoom' || currentDragMode === 'select') {
        return 'crosshair';
    }
    if (currentDragMode === 'pan') {
        return isPointerDown ? 'grabbing' : 'grab';
    }
    return;
}
function isPointInsideSpace(x, y, space) {
    if (x >= space.x && x <= space.x + space.width && y >= space.y && y <= space.y + space.height) {
        return true;
    }
    return false;
}
function isPointOutsideTargetSpace(x, y, plotAreaSpace, xSpace, ySpace) {
    if (!isPointInsideSpace(x, y, plotAreaSpace) &&
        !isPointInsideSpace(x, y, xSpace) &&
        !isPointInsideSpace(x, y, ySpace)) {
        return true;
    }
    return false;
}
function getPanButtonVisibility(isZoomAndScroll, dragMode, isMobile) {
    if (!isMobile || !isZoomAndScroll) {
        return false;
    }
    return dragMode === 'user' || dragMode === 'pan';
}
function getZoomButtonVisibility(isZoomAndScroll, isMobile, dragMode) {
    if (!isZoomAndScroll) {
        return false;
    }
    // In mobile don't show for user mode
    return (isMobile && dragMode === 'zoom') || (!isMobile && dragMode === 'user');
}
function getSelectButtonVisibility(isMultiSelection, isZoomScroll, isMobile, dragMode) {
    if (!isMultiSelection) {
        return false;
    }
    else if (!isZoomScroll && (dragMode === 'user' || dragMode === 'select')) {
        return isMobile;
    }
    return dragMode === 'user' || (isMobile && dragMode === 'select');
}

function Marquee({ x1, y1, width, height }) {
    return (jsxs(Fragment, { children: [jsx("rect", { x: x1, y: y1, width: width, height: height, class: styles.visMarquee, "data-oj-private-object": "marquee" }), jsx("rect", { x: x1 + 1, y: y1 + 1, width: Math.max(0, width - 2), height: Math.max(0, height - 2), class: styles.visMarqueeInnerArea })] }));
}

function useChartMarquee({ plotAreaSpace, xSpace, ySpace, dragMode, chartWidth, isMultiSelection, onViewportChange, isZoomScroll, xAxisExtent, xScale, selectedIds, getDataById, onSelectionChange, viewportMax, viewportMin, isRtl, xAxisMinExtent }) {
    const isDeviceTouch = isTouch();
    const isHovered = useRef(false);
    const numOfActiveTouches = useRef(0);
    const initialPointRef = useRef();
    const showPanButton = getPanButtonVisibility(isZoomScroll, dragMode, isDeviceTouch);
    const showZoomButton = getZoomButtonVisibility(isZoomScroll, isDeviceTouch, dragMode);
    const showSelectButton = getSelectButtonVisibility(isMultiSelection, isZoomScroll, isDeviceTouch, dragMode);
    const { dragButtonDivRef, toggleButtonContent, userDragMode } = useVisDragModeControls({
        componentWidth: chartWidth,
        plotAreaSpace,
        isRtl,
        showPanButton,
        showZoomButton,
        showSelectButton,
        dragMode
    });
    // for drag --> dragging cursor rerender in pan mode
    const [isPointerDown, setIsPointerDown] = useState(false);
    const isDragActiveRef = useRef(false);
    const [finalPoint, setFinalPoint] = useState();
    const selectedIdsRef = useRef(new Set());
    const isUserDragModeButtonShown = (showPanButton && userDragMode === 'pan') ||
        (showSelectButton && userDragMode === 'select') ||
        (showZoomButton && userDragMode === 'zoom');
    const mode = getResolvedDragMode(isUserDragModeButtonShown, isZoomScroll, isDeviceTouch, dragMode, userDragMode, isMultiSelection);
    const dims = getMarqueeDims(initialPointRef.current, finalPoint, plotAreaSpace, xSpace, ySpace, mode === 'zoom' // We need to revisit this for scatter chart and others charts
    );
    const onPointerEnter = () => {
        isHovered.current = true;
    };
    const onPointerDown = (event) => {
        // prevent setIsPointerDown(true) when clicked on button
        // otherwise the button will disapper before being clicked.
        if (dragButtonDivRef?.current?.contains(event.target)) {
            return;
        }
        const x = event.offsetX;
        const y = event.offsetY;
        setIsPointerDown(true);
        if (isPointOutsideTargetSpace(x, y, plotAreaSpace, xSpace, ySpace) ||
            (mode === 'zoom' && isPointInsideSpace(x, y, ySpace))) {
            return;
        }
        initialPointRef.current = { x, y };
    };
    const onPointerLeave = (event) => {
        isHovered.current = false;
        if (dims && isDeviceTouch && mode != 'off') {
            event.currentTarget.setPointerCapture(event.pointerId);
        }
    };
    const onPointerMove = (event) => {
        if (!isPointerDown) {
            return;
        }
        isDragActiveRef.current = true;
        if (event.metaKey && initialPointRef.current) {
            initialPointRef.current.isMeta = true;
        }
        const x = event.offsetX;
        const y = event.offsetY;
        if (isPointOutsideTargetSpace(x, y, plotAreaSpace, xSpace, ySpace) ||
            (mode === 'zoom' && isPointInsideSpace(x, y, ySpace))) {
            return;
        }
        if (mode === 'pan' &&
            onViewportChange &&
            (!isDeviceTouch || (isDeviceTouch && numOfActiveTouches.current === 1))) {
            const axisDelta = xScale.invert(x) - xScale.invert((finalPoint?.x || initialPointRef.current?.x));
            const viewportRange = viewportMax - viewportMin;
            let xMin = viewportMin - axisDelta;
            let xMax = viewportMax - axisDelta;
            if (xMin < xAxisExtent.min) {
                xMin = xAxisExtent.min;
                xMax = xMin + viewportRange;
            }
            if (xMax > xAxisExtent.max) {
                xMax = xAxisExtent.max;
                xMin = xMax - viewportRange;
            }
            if (xMin != viewportMin && xMax != viewportMax && Math.abs(xMax - xMin) > xAxisMinExtent) {
                onViewportChange({
                    xMin,
                    xMax
                });
            }
        }
        setFinalPoint({ x, y });
    };
    const onPointerUp = (event) => {
        setIsPointerDown(false);
        setFinalPoint(undefined);
        initialPointRef.current = undefined;
        isDragActiveRef.current = false;
        if (dragButtonDivRef.current?.contains(event.target)) {
            return;
        }
        if (!dims) {
            return;
        }
        if (mode === 'zoom') {
            const { x1, x2 } = dims;
            let xMin = Math.min(xScale.invert(x1), xScale.invert(x2));
            let xMax = Math.max(xScale.invert(x1), xScale.invert(x2));
            if (Math.abs(xMax - xMin) < xAxisMinExtent) {
                const mid = (xMin + xMax) / 2;
                xMin = Math.max(xAxisExtent.min, mid - xAxisMinExtent / 2);
                xMax = Math.min(xAxisExtent.max, xMin + xAxisMinExtent);
            }
            onViewportChange?.({
                xMin,
                xMax
            });
        }
        if (mode === 'select') {
            const ids = [
                ...new Set([
                    ...selectedIdsRef.current,
                    ...(event.metaKey ? selectedIds || new Set() : new Set())
                ])
            ];
            const data = ids.map((id) => getDataById(id));
            onSelectionChange?.({ ids, data });
            selectedIdsRef.current = new Set();
        }
    };
    // if mode is 'off', we still want to show the toggleButton.
    // pointerUp will not fire because browser will have already claimed the
    // pointer
    const onTouchEnd = (event) => {
        setIsPointerDown(false);
        setFinalPoint(undefined);
        initialPointRef.current = undefined;
        numOfActiveTouches.current = event.touches.length;
    };
    const onTouchStart = (event) => {
        numOfActiveTouches.current = event.touches.length;
    };
    let marqueeContent;
    const isPointInsideMarquee = mode === 'select' && dims
        ? (id, point) => {
            if (initialPointRef.current?.isMeta && selectedIds?.has(id)) {
                return true;
            }
            const { x1, x2, y1, y2 } = dims;
            const { x, y } = point;
            if (isPointInsideSpace(x, y, { x: x1, width: x2 - x1, y: y1, height: y2 - y1 })) {
                selectedIdsRef.current?.add(id);
                return true;
            }
            else {
                selectedIdsRef.current?.delete(id);
            }
            return false;
        }
        : undefined;
    if (dims && (mode === 'zoom' || mode === 'select')) {
        marqueeContent = jsx(Marquee, { ...dims });
    }
    return {
        ignoreSelectPointerUp: (mode === 'pan' || mode === 'zoom') && isDragActiveRef.current,
        cursor: getCursorType(mode, isPointerDown),
        yAxisCursor: mode !== 'zoom' ? getCursorType(mode, isPointerDown) : 'initial',
        marqueeContent,
        toggleButtonContent: !isPointerDown &&
            ((!isDeviceTouch && isHovered.current) || isDeviceTouch) &&
            toggleButtonContent,
        isPointInsideMarquee,
        dragMode: mode,
        marqueeProps: dragMode != 'off'
            ? {
                onPointerDown,
                onPointerMove,
                onPointerUp,
                onPointerLeave,
                onPointerEnter,
                onTouchEnd,
                onTouchStart
            }
            : {}
    };
}

export { useChartMarquee as u };
//# sourceMappingURL=useChartMarquee-7cd47205.js.map
