import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { $isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $findMatchingParent, mergeRegister } from '@lexical/utils';
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND } from 'lexical';
import { useCallback, useEffect, useState } from 'react';
import { getSelectedNode } from '../../../utils/editor';
import { isValidUrl } from '@selfcommunity/utils';
import { styled } from '@mui/material/styles';
import { IconButton, InputAdornment, Paper, Popper, TextField } from '@mui/material';
import Icon from '@mui/material/Icon';
import { PREFIX } from '../constants';
const classes = {
    root: `${PREFIX}-floating-link-plugin-root`
};
const Root = styled(Popper, {
    name: PREFIX,
    slot: 'FloatingLinkPluginRoot'
})(() => ({}));
function FloatingLinkPlugin({ editor, isLink, setIsLink }) {
    const [anchorEl, setAnchorEl] = useState(null);
    const [linkUrl, setLinkUrl] = useState('');
    const [hideForUrl, setHideForUrl] = useState(null);
    const [lastSelection, setLastSelection] = useState(null);
    const updateLinkEditor = useCallback(() => {
        var _a;
        const selection = $getSelection();
        if ($isRangeSelection(selection)) {
            const node = getSelectedNode(selection);
            const parent = node.getParent();
            if ($isLinkNode(parent)) {
                setLinkUrl(parent.getURL());
            }
            else if ($isLinkNode(node)) {
                setLinkUrl(node.getURL());
            }
            else {
                setLinkUrl('');
            }
        }
        const nativeSelection = window.getSelection();
        const activeElement = document.activeElement;
        const rootElement = editor.getRootElement();
        if (selection !== null &&
            nativeSelection !== null &&
            rootElement !== null &&
            rootElement.contains(nativeSelection.anchorNode) &&
            editor.isEditable()) {
            setAnchorEl((_a = nativeSelection.focusNode) === null || _a === void 0 ? void 0 : _a.parentElement);
            setLastSelection(selection);
        }
        else if (!activeElement) {
            setAnchorEl(null);
            setLastSelection(null);
            setLinkUrl('');
        }
        return true;
    }, [editor]);
    useEffect(() => {
        if (linkUrl != hideForUrl) {
            setHideForUrl(null);
        }
    }, [linkUrl]);
    useEffect(() => {
        return 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, updateLinkEditor, setIsLink, isLink]);
    useEffect(() => {
        editor.getEditorState().read(() => {
            updateLinkEditor();
        });
    }, [editor, updateLinkEditor]);
    const handleLinkSubmission = () => {
        if (lastSelection !== null) {
            if (linkUrl !== '') {
                setHideForUrl(linkUrl);
                editor.dispatchCommand(TOGGLE_LINK_COMMAND, isValidUrl(linkUrl) ? linkUrl : 'https://');
            }
        }
    };
    if (!isLink || linkUrl === hideForUrl) {
        return null;
    }
    return (_jsx(Root, Object.assign({ className: classes.root, open: Boolean(anchorEl), anchorEl: anchorEl, placement: "right" }, { children: _jsx(Paper, { children: _jsx(TextField, { size: "small", value: linkUrl, variant: "outlined", onChange: (event) => {
                    setLinkUrl(event.target.value);
                }, InputProps: {
                    endAdornment: (_jsxs(InputAdornment, Object.assign({ position: "end" }, { children: [_jsx(IconButton, Object.assign({ size: "small", tabIndex: 0, onClick: () => {
                                    setIsLink(false);
                                } }, { children: _jsx(Icon, { children: "close" }) })), _jsx(IconButton, Object.assign({ size: "small", tabIndex: 1, onClick: handleLinkSubmission }, { children: _jsx(Icon, { children: "check" }) }))] })))
                } }) }) })));
}
function useFloatingLinkEditorToolbar(editor) {
    const [activeEditor, setActiveEditor] = useState(editor);
    const [isLink, setIsLink] = useState(false);
    const updateToolbar = useCallback(() => {
        const selection = $getSelection();
        if ($isRangeSelection(selection)) {
            const node = getSelectedNode(selection);
            const linkParent = $findMatchingParent(node, $isLinkNode);
            const autoLinkParent = $findMatchingParent(node, $isAutoLinkNode);
            // We don't want this menu to open for auto links.
            if (linkParent != null && autoLinkParent == null) {
                setIsLink(true);
            }
            else {
                setIsLink(false);
            }
        }
    }, []);
    useEffect(() => {
        return mergeRegister(editor.registerUpdateListener(({ editorState }) => {
            editorState.read(() => {
                updateToolbar();
            });
        }), editor.registerCommand(SELECTION_CHANGE_COMMAND, (_payload, newEditor) => {
            updateToolbar();
            setActiveEditor(newEditor);
            return false;
        }, COMMAND_PRIORITY_CRITICAL));
    }, [editor, updateToolbar]);
    return _jsx(FloatingLinkPlugin, { editor: activeEditor, isLink: isLink, setIsLink: setIsLink });
}
export default () => {
    const [editor] = useLexicalComposerContext();
    return useFloatingLinkEditorToolbar(editor);
};
