import { ref, watch } from 'vue';
import { isBoolean, isFunction } from 'lodash-es';

const triggerEventsMap = {
  click: ['onClick'],
  hover: ['onMouseenter', 'onMouseleave'],
  focus: ['onFocus', 'onBlur'],
  contextmenu: ['onContextmenu', 'onClick']
};
function useTrigger(visible, updateVisible, props, updateVirtualRect) {
  let triggerFocused = false;
  let showTimer;
  let hideTimer;
  const events = ref({});
  function clearTimers() {
    clearTimeout(showTimer);
    clearTimeout(hideTimer);
  }
  const hide = () => {
    const setHide = () => {
      if (props.onlyShowTrigger) {
        return;
      }
      if (isBoolean(props.disabled) && props.disabled) {
        return;
      }
      if (isFunction(props.disabled) && props.disabled()) {
        return;
      }
      updateVisible(false);
    };
    clearTimers();
    if (props.hideAfter) {
      hideTimer = setTimeout(() => {
        setHide();
      }, props.hideAfter);
    } else {
      setHide();
    }
  };
  const show = () => {
    const setShow = () => {
      if (isBoolean(props.disabled) && props.disabled) {
        return;
      }
      if (isFunction(props.disabled) && props.disabled()) {
        return;
      }
      updateVisible(true);
    };
    clearTimers();
    if (props.showAfter) {
      showTimer = setTimeout(() => {
        setShow();
      }, props.showAfter);
    } else {
      setShow();
    }
  };
  const toggleState = () => {
    if (visible.value) {
      hide();
    } else {
      show();
    }
  };
  const popperEventsHandler = (e, t) => {
    // 不是用户触发的行为
    e.stopPropagation();
    switch (e.type) {
      case 'click':
        {
          if (t === 'contextmenu') {
            if (visible.value) {
              updateVirtualRect(null);
              toggleState();
            }
          } else if (triggerFocused) {
            // reset previous focus event
            triggerFocused = false;
          } else {
            toggleState();
          }
          break;
        }
      case 'mouseenter':
        {
          show();
          break;
        }
      case 'mouseleave':
        {
          hide();
          break;
        }
      case 'focus':
        {
          triggerFocused = true;
          show();
          break;
        }
      case 'blur':
        {
          triggerFocused = false;
          hide();
          break;
        }
      case 'contextmenu':
        {
          updateVirtualRect({
            x: e.clientX,
            y: e.clientY
          });
          e.preventDefault();
          show();
          break;
        }
    }
  };
  const mapEvents = t => {
    const _events = {};
    triggerEventsMap[t].forEach(event => {
      _events[event] = e => {
        popperEventsHandler(e, t);
      };
    });
    events.value = _events;
  };
  watch(() => props.trigger, () => {
    if (props.trigger) {
      mapEvents(props.trigger);
    }
  }, {
    immediate: true
  });
  function onPopperMouseEnter() {
    // if trigger is click, user won't be able to close popper when
    // user tries to move the mouse over popper contents
    if (props.trigger !== 'click') {
      clearTimeout(hideTimer);
    }
  }
  function onPopperMouseLeave() {
    const {
      trigger
    } = props;
    const shouldPrevent = trigger === 'click' || trigger === 'focus' || trigger === 'contextmenu';
    if (shouldPrevent) {
      return;
    }
    hide();
  }
  return {
    events,
    onPopperMouseEnter,
    onPopperMouseLeave
  };
}

export { useTrigger as default };
