import { memo, useRef, useState, useEffect } from 'react';
import type { FC, PropsWithChildren } from 'react';
import cc from 'classcat';

import { EdgeTextProps, Rect } from '../../types';

const EdgeText: FC<PropsWithChildren<EdgeTextProps>> = ({
  x,
  y,
  label,
  labelStyle = {},
  labelShowBg = true,
  labelBgStyle = {},
  labelBgPadding = [2, 4],
  labelBgBorderRadius = 2,
  children,
  className,
  ...rest
}) => {
  const edgeRef = useRef<any>(null);
  const [edgeTextBbox, setEdgeTextBbox] = useState<Rect>({ x: 0, y: 0, width: 0, height: 0 });
  const edgeTextClasses = cc(['react-flow__edge-textwrapper', className]);

  useEffect(() => {
    if (edgeRef.current) {
      const textBbox = edgeRef.current
      const body = document.body.getBoundingClientRect()
      setEdgeTextBbox({
        x: body.left - textBbox.getBoundingClientRect().left,
        y: body.top - textBbox.getBoundingClientRect().top,
        width: textBbox.offsetWidth,
        height: textBbox.offsetHeight,
      });
    }
  }, [label]);

  if (typeof label === 'undefined' || !label) {
    return null;
  }

  return (
    <g
      transform={`translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`}
      className={edgeTextClasses}
      visibility={edgeTextBbox.width ? 'visible' : 'hidden'}
      {...rest}
    >
      {labelShowBg && (
        <rect
          width={edgeTextBbox.width + 2 * labelBgPadding[0]}
          x={-labelBgPadding[0]}
          y={-labelBgPadding[1]}
          height={edgeTextBbox.height + 2 * labelBgPadding[1]}
          className="react-flow__edge-textbg"
          style={labelBgStyle}
          rx={labelBgBorderRadius}
          ry={labelBgBorderRadius}
        />
      )}
      <div className="react-flow__edge-text" ref={edgeRef} style={labelStyle}>
        {label}
      </div>
      {children}
    </g>
  );
};
export default memo(EdgeText);
