import { posToDOMRect } from "@tiptap/core";
import { ReactNode, useMemo } from "react";

import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor.js";
import { useEditorDOMElement } from "../../hooks/useEditorDomElement.js";
import { FloatingUIOptions } from "./FloatingUIOptions.js";
import { GenericPopover, GenericPopoverReference } from "./GenericPopover.js";

export const PositionPopover = (
  props: FloatingUIOptions & {
    position: { from: number; to?: number } | undefined;
    children: ReactNode;
    portalElement?: HTMLElement | null;
  },
) => {
  const { position, children, portalElement, ...floatingUIOptions } = props;
  const { from, to } = position || {};

  const editor = useBlockNoteEditor<any, any, any>();
  const editorDOMElement = useEditorDOMElement();

  const reference = useMemo<GenericPopoverReference | undefined>(() => {
    if (from === undefined || to === undefined) {
      return undefined;
    }

    return {
      // Use first child as the editor DOM element may itself be scrollable.
      // For FloatingUI to auto-update the position during scrolling, the
      // `contextElement` must be a descendant of the scroll container.
      element: editorDOMElement?.firstElementChild || undefined,
      getBoundingClientRect: () =>
        posToDOMRect(editor.prosemirrorView, from, to ?? from),
    };
  }, [editor, editorDOMElement, from, to]);

  return (
    <GenericPopover
      reference={reference}
      portalElement={portalElement}
      {...floatingUIOptions}
    >
      {position !== undefined && children}
    </GenericPopover>
  );
};
