import { useCallback, useRef, useState } from 'react';
import { NodeMouseHandler, useReactFlow } from 'reactflow';

import styles from './index.less';

export interface INodeContextMenu {
  id: string;
  top: number;
  left: number;
  right?: number;
  bottom?: number;
  [key: string]: unknown;
}

export function NodeContextMenu({
  id,
  top,
  left,
  right,
  bottom,
  ...props
}: INodeContextMenu) {
  const { getNode, setNodes, addNodes, setEdges } = useReactFlow();

  const duplicateNode = useCallback(() => {
    const node = getNode(id);
    const position = {
      x: node?.position?.x || 0 + 50,
      y: node?.position?.y || 0 + 50,
    };

    addNodes({
      ...(node || {}),
      data: node?.data,
      selected: false,
      dragging: false,
      id: `${node?.id}-copy`,
      position,
    });
  }, [id, getNode, addNodes]);

  const deleteNode = useCallback(() => {
    setNodes((nodes) => nodes.filter((node) => node.id !== id));
    setEdges((edges) => edges.filter((edge) => edge.source !== id));
  }, [id, setNodes, setEdges]);

  return (
    <div
      style={{ top, left, right, bottom }}
      className={styles.contextMenu}
      {...props}
    >
      <p style={{ margin: '0.5em' }}>
        <small>node: {id}</small>
      </p>
      <button onClick={duplicateNode} type={'button'}>
        duplicate
      </button>
      <button onClick={deleteNode} type={'button'}>
        delete
      </button>
    </div>
  );
}

export const useHandleNodeContextMenu = (sideWidth: number) => {
  const [menu, setMenu] = useState<INodeContextMenu>({} as INodeContextMenu);
  const ref = useRef<any>(null);

  const onNodeContextMenu: NodeMouseHandler = useCallback(
    (event, node) => {
      // Prevent native context menu from showing
      event.preventDefault();

      // Calculate position of the context menu. We want to make sure it
      // doesn't get positioned off-screen.
      const pane = ref.current?.getBoundingClientRect();
      // setMenu({
      //   id: node.id,
      //   top: event.clientY < pane.height - 200 ? event.clientY : 0,
      //   left: event.clientX < pane.width - 200 ? event.clientX : 0,
      //   right: event.clientX >= pane.width - 200 ? pane.width - event.clientX : 0,
      //   bottom:
      //     event.clientY >= pane.height - 200 ? pane.height - event.clientY : 0,
      // });

      setMenu({
        id: node.id,
        top: event.clientY - 144,
        left: event.clientX - sideWidth,
        // top: event.clientY < pane.height - 200 ? event.clientY - 72 : 0,
        // left: event.clientX < pane.width - 200 ? event.clientX : 0,
      });
    },
    [sideWidth],
  );

  // Close the context menu if it's open whenever the window is clicked.
  const onPaneClick = useCallback(
    () => setMenu({} as INodeContextMenu),
    [setMenu],
  );

  return { onNodeContextMenu, menu, onPaneClick, ref };
};
