import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js';
import { $wrapNodeInElement, mergeRegister } from '@lexical/utils';
import { COMMAND_PRIORITY_EDITOR, $createParagraphNode, $insertNodes, $isRootOrShadowRoot, createCommand, LexicalCommand } from 'lexical';
import { useEffect } from 'react';

import { $createImageNode, ImageNode, ImagePayload } from './node.js';

type InsertImagePayload = Readonly<ImagePayload>;

/**
 * A command to insert an image. The argument is an {@link ImagePayload}.
 */
export const INSERT_IMAGE_COMMAND: LexicalCommand<InsertImagePayload> = createCommand('INSERT_IMAGE_COMMAND');

/**
 * A Lexical plugin to register the INSERT_IMAGE_COMMAND
 */
export const ImagePlugin = (): JSX.Element | null => {
  const [editor] = useLexicalComposerContext();

  useEffect(() => {
    if (!editor.hasNodes([ImageNode])) {
      throw new Error('ImagesPlugin: ImageNode not registered on editor');
    }

    return mergeRegister(
      editor.registerCommand<InsertImagePayload>(
        INSERT_IMAGE_COMMAND,
        (payload) => {
          const imageNode = $createImageNode(payload);
          $insertNodes([imageNode]);

          if ($isRootOrShadowRoot(imageNode.getParentOrThrow())) {
            $wrapNodeInElement(imageNode, $createParagraphNode).selectEnd();
          }

          return true;
        },
        COMMAND_PRIORITY_EDITOR,
      ),
    );
  }, [editor]);

  return null;
};
