import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/
import { ArrowResetRegular } from "@fluentui/react-icons";
import { Button, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, Paper, Tooltip, useTheme, } from "@mui/material";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useLongPress } from "react-use";
import tc from "tinycolor2";
import { makeStyles } from "tss-react/mui";
import { PanelContextMenu, } from "@foxglove/studio-base/components/PanelContextMenu";
import { HUD } from "@foxglove/studio-base/panels/ThreeDeeRender/HUD";
import { InteractionContextMenu, Interactions } from "./Interactions";
import { useRenderer, useRendererEvent } from "./RendererContext";
import { Stats } from "./Stats";
import { EventEmitter } from "eventemitter3";
const PublishClickIcons = {
    pose: (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "24", height: "24", fill: "currentColor", "aria-hidden": "true", children: _jsxs("g", { children: [_jsx("circle", { cx: "12.03", cy: "18.5", r: "2" }), _jsx("path", { d: "M13.28,13.15V5H17L12,0,7.08,5h3.7v8.2a5.5,5.5,0,1,0,2.5,0ZM12,22a3.5,3.5,0,1,1,3.5-3.5A3.5,3.5,0,0,1,12,22Z" })] }) })),
    point: (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "24", height: "24", fill: "currentColor", "aria-hidden": "true", children: _jsxs("g", { children: [_jsx("circle", { cx: "12", cy: "12", r: "2" }), _jsx("path", { d: "M12,17.5A5.5,5.5,0,1,1,17.5,12,5.51,5.51,0,0,1,12,17.5Zm0-9A3.5,3.5,0,1,0,15.5,12,3.5,3.5,0,0,0,12,8.5Z" })] }) })),
    pose_estimate: (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "24", height: "24", fill: "currentColor", "aria-hidden": "true", children: _jsxs("g", { children: [_jsx("path", { d: "M.23,8.71l7.85,7.41L12,13.29l4,2.83,7.85-7.41S20.8,4,12,4,.23,8.71.23,8.71Z", opacity: "0.2" }), _jsx("circle", { cx: "12.03", cy: "18.5", r: "2" }), _jsx("path", { d: "M13.28,13.15V5H17L12,0,7.08,5h3.7v8.2a5.5,5.5,0,1,0,2.5,0ZM12,22a3.5,3.5,0,1,1,3.5-3.5A3.5,3.5,0,0,1,12,22Z" }), _jsx("path", { d: "M16,16.12,14.6,14.67l1.46-1.37,1.37,1.45Zm2.18-2.06-1.37-1.45,1.45-1.37,1.37,1.45ZM20.34,12,19,10.55l1.45-1.37,1.38,1.45ZM22.52,10,21.15,8.49l1.31-1.24,1.37,1.46Z" }), _jsx("path", { d: "M8.08,16.12,6.63,14.75,8,13.3l1.46,1.37ZM5.9,14.06,4.45,12.69l1.37-1.45,1.45,1.37ZM3.72,12,2.27,10.63,3.64,9.18l1.45,1.37ZM1.54,10,.23,8.71,1.6,7.25,2.91,8.49Z" })] }) })),
};
const useStyles = makeStyles()((theme) => ({
    root: {
        position: "absolute",
        top: 10,
        right: 10,
        display: "flex",
        flexDirection: "column",
        alignItems: "flex-end",
        gap: 10,
        pointerEvents: "none",
    },
    iconButton: {
        position: "relative",
        pointerEvents: "auto",
        aspectRatio: "1/1",
    },
    rulerIcon: {
        transform: "rotate(45deg)",
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
    },
    threeDeeButton: {
        fontFamily: theme.typography.fontMonospace,
        fontFeatureSettings: theme.typography.caption.fontFeatureSettings,
        fontSize: theme.typography.caption.fontSize,
        fontWeight: theme.typography.fontWeightBold,
        lineHeight: "1em",
    },
    resetViewButton: {
        position: "absolute",
        bottom: 0,
        right: 0,
        marginBottom: theme.spacing(1),
        marginRight: theme.spacing(1),
    },
    kbd: {
        fontFamily: theme.typography.fontMonospace,
        background: tc(theme.palette.common.white).darken(45).toString(),
        padding: theme.spacing(0, 0.5),
        aspectRatio: 1,
        borderRadius: theme.shape.borderRadius,
        marginLeft: theme.spacing(1),
    },
}));
export const on3dSceneReset = new EventEmitter();
/**
 * Provides DOM overlay elements on top of the 3D scene (e.g. stats, debug GUI).
 */
export function RendererOverlay(props) {
    const { t } = useTranslation("threeDee");
    const { classes } = useStyles();
    const [clickedPosition, setClickedPosition] = useState({
        clientX: 0,
        clientY: 0,
    });
    const [selectedRenderables, setSelectedRenderables] = useState([]);
    const [selectedRenderable, setSelectedRenderable] = useState(undefined);
    const [interactionsTabType, setInteractionsTabType] = useState(undefined);
    const renderer = useRenderer();
    // Toggle object selection mode on/off in the renderer
    useEffect(() => {
        if (renderer) {
            renderer.setPickingEnabled(interactionsTabType != undefined);
        }
    }, [interactionsTabType, renderer]);
    useRendererEvent("renderablesClicked", (selections, cursorCoords) => {
        const rect = props.canvas.getBoundingClientRect();
        setClickedPosition({ clientX: rect.left + cursorCoords.x, clientY: rect.top + cursorCoords.y });
        setSelectedRenderables(selections);
        setSelectedRenderable(selections.length === 1 ? selections[0] : undefined);
    });
    const [showResetViewButton, setShowResetViewButton] = useState(renderer?.canResetView() ?? false);
    useRendererEvent("resetViewChanged", useCallback(() => {
        setShowResetViewButton(renderer?.canResetView() ?? false);
    }, [renderer]));
    const onResetView = useCallback(() => {
        renderer?.resetView();
    }, [renderer]);
    const stats = props.enableStats ? (_jsx("div", { id: "stats", style: { position: "absolute", top: "10px", left: "10px" }, children: _jsx(Stats, {}) })) : undefined;
    // Convert the list of selected renderables (if any) into MouseEventObjects
    // that can be passed to <InteractionContextMenu>, which shows a context menu
    // of candidate objects to select
    const clickedObjects = useMemo(() => selectedRenderables.map((selection) => ({
        object: {
            pose: selection.renderable.pose,
            scale: selection.renderable.scale,
            color: undefined,
            interactionData: {
                topic: selection.renderable.name,
                highlighted: undefined,
                renderable: selection.renderable,
            },
        },
        instanceIndex: selection.instanceIndex,
    })), [selectedRenderables]);
    // Once a single renderable is selected, convert it to the SelectionObject
    // format to populate the object inspection dialog (<Interactions>)
    const selectedObject = useMemo(() => selectedRenderable
        ? {
            object: {
                pose: selectedRenderable.renderable.pose,
                interactionData: {
                    topic: selectedRenderable.renderable.topic,
                    highlighted: true,
                    originalMessage: selectedRenderable.renderable.details(),
                    instanceDetails: selectedRenderable.instanceIndex != undefined
                        ? selectedRenderable.renderable.instanceDetails(selectedRenderable.instanceIndex)
                        : undefined,
                },
            },
            instanceIndex: selectedRenderable.instanceIndex,
        }
        : undefined, [selectedRenderable]);
    // Inform the Renderer when a renderable is selected
    useEffect(() => {
        renderer?.setSelectedRenderable(selectedRenderable);
    }, [renderer, selectedRenderable]);
    const publickClickButtonRef = useRef(null);
    const [publishMenuExpanded, setPublishMenuExpanded] = useState(false);
    const selectedPublishClickIcon = PublishClickIcons[props.publishClickType];
    const onLongPressPublish = useCallback(() => {
        setPublishMenuExpanded(true);
    }, []);
    const longPressPublishEvent = useLongPress(onLongPressPublish);
    const theme = useTheme();
    // Publish control is only available if the canPublish prop is true and we have a fixed frame in the renderer
    const showPublishControl = props.interfaceMode === "3d" && props.canPublish && renderer?.fixedFrameId != undefined;
    const publishControls = showPublishControl && (_jsxs(_Fragment, { children: [_jsx(Tooltip, { placement: "left", title: props.publishActive ? "Click to cancel" : "Click to publish", children: _jsxs(IconButton, { ...longPressPublishEvent, className: classes.iconButton, size: "small", color: props.publishActive ? "info" : "inherit", ref: publickClickButtonRef, onClick: props.onClickPublish, "data-testid": "publish-button", children: [selectedPublishClickIcon, _jsx("div", { style: {
                                borderBottom: "6px solid currentColor",
                                borderRight: "6px solid transparent",
                                bottom: 0,
                                left: 0,
                                height: 0,
                                width: 0,
                                margin: theme.spacing(0.25),
                                position: "absolute",
                            } })] }) }), _jsxs(Menu, { id: "publish-menu", anchorEl: publickClickButtonRef.current, anchorOrigin: { vertical: "top", horizontal: "left" }, transformOrigin: { vertical: "top", horizontal: "right" }, open: publishMenuExpanded, onClose: () => {
                    setPublishMenuExpanded(false);
                }, MenuListProps: { dense: true }, children: [_jsxs(MenuItem, { selected: props.publishClickType === "pose_estimate", onClick: () => {
                            props.onChangePublishClickType("pose_estimate");
                            setPublishMenuExpanded(false);
                        }, children: [_jsx(ListItemIcon, { children: PublishClickIcons.pose_estimate }), _jsx(ListItemText, { disableTypography: true, children: "Publish pose estimate" })] }), _jsxs(MenuItem, { selected: props.publishClickType === "pose", onClick: () => {
                            props.onChangePublishClickType("pose");
                            setPublishMenuExpanded(false);
                        }, children: [_jsx(ListItemIcon, { children: PublishClickIcons.pose }), _jsx(ListItemText, { disableTypography: true, children: "Publish pose" })] }), _jsxs(MenuItem, { selected: props.publishClickType === "point", onClick: () => {
                            props.onChangePublishClickType("point");
                            setPublishMenuExpanded(false);
                        }, children: [_jsx(ListItemIcon, { children: PublishClickIcons.point }), _jsx(ListItemText, { disableTypography: true, children: "Publish point" })] })] })] }));
    const resetViewButton = showResetViewButton && (_jsx(Button, { className: classes.resetViewButton, variant: "contained", color: "secondary", onClick: onResetView, "data-testid": "reset-view", children: t("resetView") }));
    const getContextMenuItems = useCallback(() => {
        return renderer?.getContextMenuItems() ?? [];
    }, [renderer]);
    return (_jsxs(_Fragment, { children: [props.interfaceMode === "image" && _jsx(PanelContextMenu, { getItems: getContextMenuItems }), _jsxs("div", { className: classes.root, children: [props.interfaceMode === "3d" && (_jsx(Interactions, { addPanel: props.addPanel, interactionsTabType: interactionsTabType, onShowTopicSettings: props.onShowTopicSettings, selectedObject: selectedObject, setInteractionsTabType: setInteractionsTabType, timezone: props.timezone })), props.interfaceMode === "3d" && (_jsxs(Paper, { square: false, elevation: 4, style: { display: "flex", flexDirection: "column" }, children: [_jsx(Tooltip, { placement: "left", title: "Reset view", children: _jsx(IconButton, { className: classes.iconButton, size: "small", color: "inherit", onClick: () => {
                                        on3dSceneReset.emit("resetView");
                                    }, style: { width: "34px", height: "34px" }, children: _jsx(ArrowResetRegular, {}) }) }), publishControls] })), props.interfaceMode === "3d" && (_jsxs(Paper, { square: false, elevation: 4, style: { display: "flex", flexDirection: "column" }, children: [_jsx(Tooltip, { placement: "left", title: _jsxs("div", { children: [_jsxs("p", { className: "text-lg", children: ["Toggle camera to", " ", _jsx("span", { style: { fontWeight: "bold" }, children: !renderer?.config.cameraState.perspective ? "perspective" : "orthographic" })] }), _jsxs("div", { style: { marginTop: "0.5rem" }, children: [_jsx("p", { children: "Perspective camera is best for:" }), _jsxs("ul", { style: {
                                                        marginLeft: "2rem",
                                                        listStyleType: "disc",
                                                        listStylePosition: "inside",
                                                        fontSize: "1rem",
                                                    }, children: [_jsx("li", { children: "Realistic depth with foreshortening" }), _jsx("li", { children: "Distant objects appearing smaller" }), _jsx("li", { children: "Natural, camera-like navigation and context" })] })] }), _jsxs("div", { style: { marginTop: "0.5rem" }, children: [_jsx("p", { children: "Orthographic camera is best for:" }), _jsxs("ul", { style: {
                                                        marginLeft: "2rem",
                                                        listStyleType: "disc",
                                                        listStylePosition: "inside",
                                                        fontSize: "1rem",
                                                    }, children: [_jsx("li", { children: "No perspective distortion" }), _jsx("li", { children: "Parallel lines remain parallel" }), _jsx("li", { children: "True scale for measuring, aligning, and inspecting" })] })] })] }), children: _jsx(IconButton, { className: classes.iconButton, size: "small", style: { width: "34px", height: "34px" }, color: "inherit", onClick: () => {
                                        renderer?.updateConfig((draft) => {
                                            draft.cameraState.perspective = !renderer?.config.cameraState.perspective;
                                            localStorage.setItem("perspective", draft.cameraState.perspective.toString());
                                        });
                                    }, children: renderer?.config.cameraState.perspective ? (_jsxs("svg", { stroke: "currentColor", fill: "none", "stroke-width": "2", viewBox: "0 0 24 24", "stroke-linecap": "round", "stroke-linejoin": "round", height: "24px", width: "24px", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M4 4v16h16" }), _jsx("path", { d: "m4 20 7-7" })] })) : (_jsx("svg", { stroke: "currentColor", fill: "none", "stroke-width": "2", viewBox: "0 0 24 24", "stroke-linecap": "round", "stroke-linejoin": "round", height: "24px", width: "24px", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M6.141 4.163l12 1.714a1 1 0 0 1 .859 .99v10.266a1 1 0 0 1 -.859 .99l-12 1.714a1 1 0 0 1 -1.141 -.99v-13.694a1 1 0 0 1 1.141 -.99z" }) })) }) }), publishControls] }))] }), clickedObjects.length > 1 && !selectedObject && (_jsx(InteractionContextMenu, { onClose: () => {
                    setSelectedRenderables([]);
                }, clickedPosition: clickedPosition, clickedObjects: clickedObjects, selectObject: (selection) => {
                    if (selection) {
                        const renderable = selection.object.interactionData.renderable;
                        const instanceIndex = selection.instanceIndex;
                        setSelectedRenderables([]);
                        setSelectedRenderable({ renderable, instanceIndex });
                    }
                } })), _jsx(HUD, { renderer: renderer }), stats, resetViewButton, props.customOverlay] }));
}
//# sourceMappingURL=RendererOverlay.js.map