import React from 'react';
import { FloatingTooltip } from '../common/FloatingTooltip';

export type TooltipProps<T> = {
  data: T & { formattedValue?: string };
  top: number;
  left: number;
};

export type TooltipSetter<T = any> = (props: TooltipProps<T> | null) => void;

export type TooltipBinder<T> = (
  data?: T,
  formattedValue?: string
) =>
  | {
      onMouseEnter: (ev: React.MouseEvent<Element, MouseEvent>) => void;
      onMouseLeave: () => void;
    }
  | undefined;

export function useTooltip<T = any>(
  showTooltip: boolean,
  leaveDelay: number = 140
) {
  const [props, setProps] = React.useState<TooltipProps<T> | null>(null);
  const timeout = React.useRef<any>(null);

  const bindTooltip: TooltipBinder<T> = React.useCallback(
    (data, formattedValue) => {
      if (!data) return;

      const handleMouseEnter = (ev: React.MouseEvent) => {
        if (timeout.current) {
          clearTimeout(timeout.current);
          timeout.current = null;
        }
        setProps({
          data: formattedValue ? { ...data, formattedValue } : data,
          top: ev.clientY,
          left: ev.clientX,
        });
      };

      const handleMouseLeave = () => {
        timeout.current = setTimeout(() => {
          setProps(null);
        }, leaveDelay);
      };

      return {
        onMouseEnter: handleMouseEnter,
        onMouseLeave: handleMouseLeave,
      };
    },
    [showTooltip]
  );

  const renderTooltip = (
    component?: (data: TooltipProps<T>['data']) => JSX.Element
  ) => {
    if (component && showTooltip && props) {
      const tooltipComponent =
        typeof component === 'function' ? component(props.data) : component;
      if (tooltipComponent) {
        return (
          <FloatingTooltip top={props.top} left={props.left}>
            {tooltipComponent}
          </FloatingTooltip>
        );
      } else {
        return null;
      }
    } else {
      return null;
    }
  };

  return {
    bindTooltip: showTooltip ? bindTooltip : undefined,
    renderTooltip,
    tooltip: props,
    setTooltip: setProps,
  };
}
