import { forwardRef, useEffect, useRef } from 'react';

import { Controller } from './Controller';
import { Popup } from './Popup';

export const TOP = 0;
export const BOTTOM = 1;
export const LEFT = 2;
export const RIGHT = 3;

export const START = 0;
export const CENTER = 1;
export const END = 2;
export const STRETCH = 3;

type Position = 0 | 1 | 2 | 3;

export type PopupControllerProps = {
  anchor: Element;
  component: React.ReactElement | ((close: () => void) => React.ReactElement);
  placement?: Position;
  alignment?: Position;
  trigger?: 'click' | 'hover';
  // mouseEnterDelay?: number;
  mouseLeaveDelay?: number;
  // relativeToAnchor?: boolean;
  onDismiss: () => void;
};

export const PopupController = forwardRef<HTMLDivElement, PopupControllerProps>(
  (
    {
      anchor,
      component,
      placement = BOTTOM,
      alignment = END,
      trigger = 'click',
      // mouseEnterDelay = 0,
      mouseLeaveDelay = 0,
      // relativeToAnchor,
      onDismiss,
    },
    ref
  ) => {
    const popupRef = useRef<HTMLDivElement>(null);
    const leaveTimer = useRef<any>(null);
    // const enterTimer = useRef(null);

    function closePopup() {
      onDismiss();
    }

    const onClickOutside = (ev: MouseEvent) => {
      if (ev.target !== anchor) {
        onDismiss();
      }
    };

    const onMouseEnter: React.MouseEventHandler = (ev) => {
      if (leaveTimer.current) {
        clearTimeout(leaveTimer.current);
      }
      // enterTimer.current = setTimeout(() => {
      //   isOpen(true);
      // }, mouseEnterDelay);
    };

    const onMouseLeave: React.MouseEventHandler = (ev) => {
      if (ev.relatedTarget === anchor) return;
      // if (enterTimer.current) {
      //   clearTimeout(enterTimer.current);
      // }
      leaveTimer.current = setTimeout(() => {
        onDismiss();
      }, mouseLeaveDelay);
    };

    useEffect(() => {
      return () => {
        if (leaveTimer.current) {
          clearTimeout(leaveTimer.current);
        }
      };
    });

    // TODO refactor componentRef
    return (
      <Controller
        componentRef={ref || popupRef}
        onClickOutside={onClickOutside}
        onScroll={closePopup}
        onResize={closePopup}
      >
        <Popup
          ref={ref || popupRef}
          anchor={anchor}
          // relativeToAnchor={relativeToAnchor}
          alignment={alignment}
          placement={placement}
          events={
            trigger === 'hover'
              ? {
                  onMouseEnter: onMouseEnter,
                  onMouseLeave: onMouseLeave,
                }
              : undefined
          }
        >
          {typeof component === 'function' ? component(closePopup) : component}
        </Popup>
      </Controller>
    );
  }
);

export default PopupController;
