"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { getClientConfig, resolveRoutes } from "@byline/core";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $findMatchingParent, mergeRegister } from "@lexical/utils";
import { $getSelection, $isLineBreakNode, $isRangeSelection, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND } from "lexical";
import { createPortal } from "react-dom";
import { $isAutoLinkNode, $isLinkNode, OPEN_LINK_MODAL_COMMAND, TOGGLE_LINK_COMMAND } from "../../../nodes/link-nodes/index.js";
import { getSelectedNode } from "../../../utils/getSelectedNode.js";
import { setFloatingElemPositionForLinkEditor } from "../../../utils/setFloatingElemPositionForLinkEditor.js";
import { sanitizeUrl } from "../../../utils/url.js";
import { LinkModal } from "./link-modal.js";
import "./floating-link-editor.css";
function FloatingLinkEditor({ editor, isLink, setIsLink, anchorElem }) {
    const editorRef = useRef(null);
    const [linkEditorState, setLinkEditorState] = useState({
        label: null,
        url: ''
    });
    const [linkModalData, setLinkModalData] = useState(void 0);
    const [modalOpen, setModalOpen] = useState(false);
    const adminRoute = useMemo(()=>resolveRoutes(getClientConfig().routes).admin, []);
    const $updateLinkEditor = useCallback(()=>{
        const selection = $getSelection();
        if ($isRangeSelection(selection)) {
            const node = getSelectedNode(selection);
            const linkParent = $findMatchingParent(node, $isLinkNode);
            let data = {
                text: '',
                fields: {
                    linkType: 'custom',
                    url: '',
                    newTab: void 0
                }
            };
            const linkNode = linkParent ?? ($isLinkNode(node) ? node : null);
            if (null != linkNode) {
                data = {
                    text: linkNode.getTextContent(),
                    fields: linkNode.getAttributes()
                };
                if (data.fields?.linkType === 'internal') {
                    const internal = data.fields;
                    setLinkEditorState({
                        label: `${internal.targetCollectionPath} · ${internal.targetDocumentId.slice(0, 8)}…`,
                        url: `${adminRoute}/collections/${internal.targetCollectionPath}/${internal.targetDocumentId}`
                    });
                } else setLinkEditorState({
                    label: null,
                    url: data.fields?.url ?? ''
                });
            } else setLinkEditorState({
                label: null,
                url: ''
            });
            setLinkModalData(data);
        }
        const editorElem = editorRef.current;
        const nativeSelection = window.getSelection();
        const { activeElement } = document;
        if (null === editorElem) return;
        const rootElement = editor.getRootElement();
        if (null !== selection && null !== nativeSelection && rootElement?.contains(nativeSelection.anchorNode) && editor.isEditable()) {
            const domRect = nativeSelection.focusNode?.parentElement?.getBoundingClientRect();
            if (null != domRect) {
                domRect.y += 40;
                setFloatingElemPositionForLinkEditor(domRect, editorElem, anchorElem);
            }
        } else if (null == activeElement || 'link-input' !== activeElement.className) {
            if (null !== rootElement) setFloatingElemPositionForLinkEditor(null, editorElem, anchorElem);
            setLinkEditorState({
                label: null,
                url: ''
            });
        }
        return true;
    }, [
        anchorElem,
        editor,
        adminRoute
    ]);
    useEffect(()=>{
        const scrollerElem = anchorElem.parentElement;
        const update = ()=>{
            editor.getEditorState().read(()=>{
                $updateLinkEditor();
            });
        };
        window.addEventListener('resize', update);
        if (null != scrollerElem) scrollerElem.addEventListener('scroll', update);
        return ()=>{
            window.removeEventListener('resize', update);
            if (null != scrollerElem) scrollerElem.removeEventListener('scroll', update);
        };
    }, [
        anchorElem.parentElement,
        editor,
        $updateLinkEditor
    ]);
    useEffect(()=>mergeRegister(editor.registerUpdateListener(({ editorState })=>{
            editorState.read(()=>{
                $updateLinkEditor();
            });
        }), editor.registerCommand(SELECTION_CHANGE_COMMAND, ()=>{
            $updateLinkEditor();
            return true;
        }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ESCAPE_COMMAND, ()=>{
            if (isLink) {
                setIsLink(false);
                return true;
            }
            return false;
        }, COMMAND_PRIORITY_HIGH), editor.registerCommand(OPEN_LINK_MODAL_COMMAND, ()=>{
            setModalOpen(true);
            return true;
        }, COMMAND_PRIORITY_LOW)), [
        editor,
        $updateLinkEditor,
        setIsLink,
        isLink
    ]);
    useEffect(()=>{
        editor.getEditorState().read(()=>{
            $updateLinkEditor();
        });
    }, [
        editor,
        $updateLinkEditor
    ]);
    const handleModalSubmit = (data)=>{
        const newAttributes = {
            ...data.fields,
            text: data.text ?? void 0
        };
        editor.dispatchCommand(TOGGLE_LINK_COMMAND, newAttributes);
    };
    return /*#__PURE__*/ jsx("div", {
        ref: editorRef,
        className: "link-editor",
        children: isLink && /*#__PURE__*/ jsxs(Fragment, {
            children: [
                /*#__PURE__*/ jsxs("div", {
                    className: "link-input",
                    children: [
                        /*#__PURE__*/ jsx("a", {
                            href: sanitizeUrl(linkEditorState.url),
                            target: "_blank",
                            rel: "noopener noreferrer",
                            children: null != linkEditorState.label && linkEditorState.label.length > 0 ? linkEditorState.label : linkEditorState.url
                        }),
                        /*#__PURE__*/ jsx("div", {
                            "aria-label": "Edit link",
                            className: "link-edit",
                            role: "button",
                            tabIndex: 0,
                            onMouseDown: (event)=>event.preventDefault(),
                            onClick: ()=>setModalOpen(true),
                            onKeyDown: (event)=>{
                                if ('Enter' === event.key || ' ' === event.key) {
                                    event.preventDefault();
                                    setModalOpen(true);
                                }
                            }
                        }),
                        /*#__PURE__*/ jsx("div", {
                            "aria-label": "Remove link",
                            className: "link-trash",
                            role: "button",
                            tabIndex: 0,
                            onMouseDown: (event)=>event.preventDefault(),
                            onClick: ()=>editor.dispatchCommand(TOGGLE_LINK_COMMAND, null),
                            onKeyDown: (event)=>{
                                if ('Enter' === event.key || ' ' === event.key) {
                                    event.preventDefault();
                                    editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
                                }
                            }
                        })
                    ]
                }),
                /*#__PURE__*/ jsx(LinkModal, {
                    isOpen: modalOpen,
                    data: linkModalData,
                    onSubmit: handleModalSubmit,
                    onClose: ()=>setModalOpen(false)
                })
            ]
        })
    });
}
function useFloatingLinkEditor(editor, anchorElem) {
    const [activeEditor, setActiveEditor] = useState(editor);
    const [isLink, setIsLink] = useState(false);
    useEffect(()=>{
        const $determineIsLink = ()=>{
            const selection = $getSelection();
            if ($isRangeSelection(selection)) {
                const focusNode = getSelectedNode(selection);
                const focusLinkNode = $findMatchingParent(focusNode, $isLinkNode);
                const focusAutoLinkNode = $findMatchingParent(focusNode, $isAutoLinkNode);
                if (null == focusLinkNode && null == focusAutoLinkNode) return void setIsLink(false);
                const invalidLinkNode = selection.getNodes().filter((node)=>!$isLineBreakNode(node)).find((node)=>{
                    const linkNode = $findMatchingParent(node, $isLinkNode);
                    const autoLinkNode = $findMatchingParent(node, $isAutoLinkNode);
                    return focusLinkNode && !focusLinkNode.is(linkNode) || linkNode && !linkNode.is(focusLinkNode) || focusAutoLinkNode && !focusAutoLinkNode.is(autoLinkNode) || autoLinkNode && !autoLinkNode.is(focusAutoLinkNode);
                });
                setIsLink(null == invalidLinkNode);
            }
        };
        return mergeRegister(editor.registerUpdateListener(({ editorState })=>{
            editorState.read(()=>{
                $determineIsLink();
            });
        }), editor.registerCommand(SELECTION_CHANGE_COMMAND, (_payload, newEditor)=>{
            $determineIsLink();
            setActiveEditor(newEditor);
            return false;
        }, COMMAND_PRIORITY_CRITICAL));
    }, [
        editor
    ]);
    return /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx(FloatingLinkEditor, {
        editor: activeEditor,
        anchorElem: anchorElem,
        isLink: isLink,
        setIsLink: setIsLink
    }), anchorElem);
}
function FloatingLinkEditorPlugin({ anchorElem = document.body }) {
    const [editor] = useLexicalComposerContext();
    return useFloatingLinkEditor(editor, anchorElem);
}
export { FloatingLinkEditorPlugin };
