import { useCallback, useEffect } from 'react';
import { useExactClick } from 'hooks/useExactClick';
import { call } from 'utils/call';

import { Layer } from './Layer';
import { FocusTrap } from './FocusTrap';

import './Modal.css';

const isEscapeEvent = function (ev: KeyboardEvent) {
  return ev.key === 'Escape' || ev.key === 'Esc' || ev.keyCode === 27;
};

export type ModalPropsType = {
  role?: string;
  label?: string;
  onDismiss: () => void;
  dismissOnOutsideClick?: boolean;
  dismissOnEscKey?: boolean;
  focusable?: boolean;
  uppermost?: boolean;
  children: React.ReactNode;
};

// TODO refactor 'uppermost' props
export const Modal = ({
  role = 'dialog',
  label,
  onDismiss,
  dismissOnOutsideClick = true,
  dismissOnEscKey = true,
  focusable = true,
  uppermost,
  children,
}: ModalPropsType) => {
  const handleClick = useCallback(
    (ev) => {
      if (ev.target === ev.currentTarget) {
        call(onDismiss);
      }
    },
    [onDismiss]
  );
  const { onMouseDown, onMouseUp } = useExactClick(handleClick);

  const handleEscape = useCallback(
    (ev) => {
      if (isEscapeEvent(ev)) {
        call(onDismiss);
      }
    },
    [onDismiss]
  );

  useEffect(() => {
    if (dismissOnEscKey && uppermost) {
      window.addEventListener('keyup', handleEscape);
      return () => {
        window.removeEventListener('keyup', handleEscape);
      };
    }
  }, [dismissOnEscKey, uppermost, handleEscape]);

  let overlayProps = {};
  if (dismissOnOutsideClick) {
    overlayProps = { onMouseDown, onMouseUp };
  }

  return (
    <Layer>
      <FocusTrap disabled={!uppermost}>
        <div className="modal-overlay" {...overlayProps}>
          <div
            style={{ outline: 'none' }}
            aria-modal={true}
            aria-label={label}
            role={role}
            tabIndex={focusable ? -1 : undefined}
          >
            {children}
          </div>
        </div>
      </FocusTrap>
    </Layer>
  );
};
