// @flow
import React, { useRef, useEffect, useCallback } from 'react';
import type { ClickOutsideProps } from './click-outside.proptypes';

const useClickOutsideState = (onClickOutside) => {
  const containerRef = useRef(null);

  const onClickOutsideHandler = useCallback(
    (event: MouseEvent) => {
      const containerElement = containerRef.current;

      if (
        containerElement &&
        event.target instanceof Node &&
        !containerElement.contains(event.target)
      ) {
        onClickOutside(event);
      }
    },
    [onClickOutside],
  );

  useEffect(() => {
    document.addEventListener('click', onClickOutsideHandler, true);

    return () => {
      document.removeEventListener('click', onClickOutsideHandler, true);
    };
  }, [onClickOutsideHandler]);

  return { containerRef };
};

export const ClickOutside = ({
  children,
  onClickOutside,
  'data-qa': dataQa,
  'data-cy': dataCy,
  id,
  ...props
}: ClickOutsideProps) => {
  const { containerRef } = useClickOutsideState(onClickOutside);
  return (
    <div
      ref={containerRef}
      data-cy={dataCy}
      data-qa={dataQa}
      id={id}
      {...props}
    >
      {children}
    </div>
  );
};

ClickOutside.displayName = 'ClickOutside';
