import { useState, useEffect, useRef } from 'react';
import { useFloating, shift, flip, arrow, offset } from '@floating-ui/react-dom';
import { useThemeByComponent } from "../uclprovider/UCLProvider";
import selectn from 'selectn'
import useEscapeEffect from '../../custom-hooks/useEscapeEffect'
import debounce from '../../utils/debounce'
import useCommonReducer from '../../libraries/reducerHandler';
import tooltipReducer, { initialState } from './Tooltip.reducers';
import { reset, setTitle } from './Tooltip.actions';
import { getClosestTitleElement } from './utils';
import { DATA_TITLE_ATTR, TITLE_ATTR, DATA_TITLE_ISHTML, TOOLTIP_DELAY, COMPONENT_NAME, ARROW_PLACEMENT } from './Tooltip.constants';

export default function useTooltip({ container, reducer, offsetOption, placement: tooltipPlacement }) {

  let { state, dispatch } = useCommonReducer(tooltipReducer, reducer, initialState)
  let arrowReference = useRef(null);
  const { x, y, reference, floating, strategy: position, middlewareData, placement } =
    useFloating({
      placement: tooltipPlacement,
      middleware: [offset(offsetOption), flip(), shift(), arrow({ element: arrowReference })]
    });
  let { title, isHtmlTitle } = state;
  useEscapeEffect(() => {
    handleReset()
  }, [title])


  let componentThemeProps = useThemeByComponent(COMPONENT_NAME);

  function handleReset() {
    if (title) {
      dispatch(reset());
    }
  }
  function mouseHover(e) {
    //For handling nested tooltip avoid call multiple times
    if (e.isTooltipHanlde) {
      handleReset()
      return null;
    }
    let element = e.target;
    let titleElement = getClosestTitleElement(element);
    if (titleElement) {
      let title =
        titleElement.getAttribute(DATA_TITLE_ATTR) || titleElement.getAttribute(TITLE_ATTR);
      if (title != "") {
        titleElement.setAttribute(DATA_TITLE_ATTR, title);
        /* reason for removing title attribute avoiding default browser tooltip*/
        titleElement.removeAttribute(TITLE_ATTR);
      }

      let isHtmlTitle = titleElement.getAttribute(DATA_TITLE_ISHTML);
      if (isHtmlTitle) {
        dispatch(setTitle(title, isHtmlTitle == "true" ? true : false));
      } else {
        dispatch(setTitle(title));
      }
      e.isTooltipHanlde = true;
      reference(titleElement);
    }
    else {
      handleReset();
    }
  }

  let mouseHoverDebounced = debounce(mouseHover, TOOLTIP_DELAY);
  useEffect(() => {
    container.addEventListener("mouseover", mouseHoverDebounced)
    container.addEventListener("mouseleave", handleReset);
    container.addEventListener("click", handleReset)
    return () => {
      container.removeEventListener("mouseover", mouseHoverDebounced);
      container.removeEventListener("mouseleave", handleReset);
      container.removeEventListener("click", handleReset)
    }
  }, [title, container])
  let arrowX = selectn("arrow.x", middlewareData);
  let arrowY = selectn("arrow.y", middlewareData);

  return {
    title, isHtmlTitle, floating,
    position, x, y, arrowReference, arrowX, arrowY,
    arrowPlacement: ARROW_PLACEMENT[placement.split('-')[0]],
    componentThemeProps
  }
}