import { jsx, jsxs } from "react/jsx-runtime";
import { Suspense, useCallback, useEffect, useRef, useState } from "react";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer";
import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection";
import { mergeRegister } from "@lexical/utils";
import classnames from "classnames";
import { $getNodeByKey, $getSelection, $isNodeSelection, $setSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, DRAGSTART_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND } from "lexical";
import content_editable_inline from "../../content-editable-inline.js";
import { useSharedHistoryContext } from "../../context/shared-history-context.js";
import { useSharedOnChange } from "../../context/shared-on-change-context.js";
import { FloatingTextFormatToolbarPlugin } from "../../plugins/floating-text-format-toolbar-plugin/index.js";
import { OPEN_INLINE_IMAGE_MODAL_COMMAND } from "../../plugins/inline-image-plugin/index.js";
import { LinkPlugin } from "../../plugins/link-plugin/link/index.js";
import { FloatingLinkEditorPlugin } from "../../plugins/link-plugin/link/floating-link-editor.js";
import placeholder_inline from "../../ui/placeholder-inline.js";
import { $isInlineImageNode } from "./inline-image-node.js";
import "./inline-image-node-component.css";
const imageCache = new Set();
async function useSuspenseImage(src) {
    if (!imageCache.has(src)) await new Promise((resolve)=>{
        const img = new Image();
        img.src = src;
        img.onload = ()=>{
            imageCache.add(src);
            resolve(null);
        };
    });
}
function LazyImage({ id, collection, src, position, altText, className, imageRef, width, height }) {
    useSuspenseImage(src);
    return /*#__PURE__*/ jsx("img", {
        className: className,
        src: src,
        alt: altText,
        ref: imageRef,
        width: width,
        height: height,
        "data-id": id,
        "data-collection": collection,
        "data-position": position,
        style: {
            display: 'block'
        },
        draggable: "false"
    });
}
function InlineImageComponent({ relation, src, position, altText, width, height, showCaption, caption, nodeKey }) {
    const { targetDocumentId: id, targetCollectionPath: collection } = relation;
    const [editor] = useLexicalComposerContext();
    const { onChange } = useSharedOnChange();
    const { historyState } = useSharedHistoryContext();
    const imageRef = useRef(null);
    const buttonRef = useRef(null);
    const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);
    const [selection, setSelection] = useState(null);
    const activeEditorRef = useRef(null);
    const onDelete = useCallback((payload)=>{
        if (isSelected && $isNodeSelection($getSelection())) {
            const event = payload;
            event.preventDefault();
            const node = $getNodeByKey(nodeKey);
            if ($isInlineImageNode(node)) node?.remove();
            setSelected(false);
        }
        return false;
    }, [
        isSelected,
        nodeKey,
        setSelected
    ]);
    const onEnter = useCallback((event)=>{
        const latestSelection = $getSelection();
        const buttonElem = buttonRef.current;
        if (isSelected && $isNodeSelection(latestSelection) && 1 === latestSelection.getNodes().length) {
            if (showCaption) {
                $setSelection(null);
                event.preventDefault();
                caption.focus();
                return true;
            } else if (null !== buttonElem && buttonElem !== document.activeElement) {
                event.preventDefault();
                buttonElem.focus();
                return true;
            }
        }
        return false;
    }, [
        caption,
        isSelected,
        showCaption
    ]);
    const onEscape = useCallback((event)=>{
        if (activeEditorRef.current === caption || buttonRef.current === event.target) {
            $setSelection(null);
            editor.update(()=>{
                setSelected(true);
                const parentRootElement = editor.getRootElement();
                if (null !== parentRootElement) parentRootElement.focus();
            });
            return true;
        }
        return false;
    }, [
        caption,
        editor,
        setSelected
    ]);
    useEffect(()=>{
        let isMounted = true;
        const unregister = mergeRegister(editor.registerUpdateListener(({ editorState })=>{
            if (isMounted) setSelection(editorState.read(()=>$getSelection()));
        }), editor.registerCommand(SELECTION_CHANGE_COMMAND, (_, activeEditor)=>{
            activeEditorRef.current = activeEditor;
            return false;
        }, COMMAND_PRIORITY_LOW), editor.registerCommand(CLICK_COMMAND, (payload)=>{
            const event = payload;
            if (event.target === imageRef.current) {
                if (event.shiftKey) setSelected(!isSelected);
                else {
                    clearSelection();
                    setSelected(true);
                }
                return true;
            }
            return false;
        }, COMMAND_PRIORITY_LOW), editor.registerCommand(DRAGSTART_COMMAND, (event)=>{
            if (event.target === imageRef.current) {
                event.preventDefault();
                return true;
            }
            return false;
        }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_DELETE_COMMAND, onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_BACKSPACE_COMMAND, onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ENTER_COMMAND, onEnter, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ESCAPE_COMMAND, onEscape, COMMAND_PRIORITY_LOW));
        return ()=>{
            isMounted = false;
            unregister();
        };
    }, [
        clearSelection,
        editor,
        isSelected,
        onDelete,
        onEnter,
        onEscape,
        setSelected
    ]);
    const draggable = isSelected && $isNodeSelection(selection);
    const isFocused = isSelected;
    const handleToggleModal = ()=>{
        editor.dispatchCommand(OPEN_INLINE_IMAGE_MODAL_COMMAND, {
            nodeKey
        });
    };
    const classNames = classnames('InlineImageNode__container', {
        focused: isFocused
    }, {
        draggable: $isNodeSelection(selection)
    });
    return /*#__PURE__*/ jsx(Suspense, {
        fallback: null,
        children: /*#__PURE__*/ jsxs("span", {
            draggable: draggable,
            className: classNames,
            children: [
                /*#__PURE__*/ jsx("button", {
                    type: "button",
                    className: "image-edit-button",
                    ref: buttonRef,
                    onClick: handleToggleModal,
                    children: "Edit"
                }),
                /*#__PURE__*/ jsx(LazyImage, {
                    id: id,
                    collection: collection,
                    src: src,
                    position: position,
                    altText: altText,
                    imageRef: imageRef,
                    width: width,
                    height: height
                }),
                showCaption && /*#__PURE__*/ jsx("span", {
                    className: "InlineImageNode__caption_container",
                    children: /*#__PURE__*/ jsxs(LexicalNestedComposer, {
                        initialEditor: caption,
                        children: [
                            /*#__PURE__*/ jsx(OnChangePlugin, {
                                ignoreSelectionChange: true,
                                onChange: (_nestedEditorState, _nestedEditor, nestedTags)=>{
                                    const editorState = editor.getEditorState();
                                    if (null != onChange) onChange(editorState, editor, nestedTags);
                                }
                            }),
                            /*#__PURE__*/ jsx(LinkPlugin, {}),
                            /*#__PURE__*/ jsx(FloatingLinkEditorPlugin, {}),
                            /*#__PURE__*/ jsx(FloatingTextFormatToolbarPlugin, {}),
                            /*#__PURE__*/ jsx(HistoryPlugin, {
                                externalHistoryState: historyState
                            }),
                            /*#__PURE__*/ jsx(RichTextPlugin, {
                                contentEditable: /*#__PURE__*/ jsx(content_editable_inline, {
                                    className: "InlineImageNode__contentEditable"
                                }),
                                placeholder: /*#__PURE__*/ jsx(placeholder_inline, {
                                    className: "InlineImageNode__placeholder",
                                    children: "Enter a caption..."
                                }),
                                ErrorBoundary: LexicalErrorBoundary
                            })
                        ]
                    })
                })
            ]
        })
    });
}
export default InlineImageComponent;
