import clsx from 'clsx';
import React, { useState } from 'react';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { noop } from '../../helpers/utils';
import classes from './Modal.scss';

export interface ModalProps {
  /** Whether the Modal is shown or not */
  isShown: boolean;
  /** Top padding (default: '70px') */
  paddingTop?: string;
  /** Right padding (default: '20px') */
  paddingRight?: string;
  /** Bottom padding (default: '20px') */
  paddingBottom?: string;
  /** Left padding (default: '20px') */
  paddingLeft?: string;
  /** Modal width (default: undefined) */
  width?: string;
  /** z-index value (default: '9999') */
  zIndex?: string;
  /** Callback to emit when the modal is mounted */
  onOpen?: () => void;
  /** Callback to emit when the when the modal is unmounted */
  onClose?: () => void;
  /** Callback to emit when the back-drop has been clicked */
  onBackDropClicked?: () => void;
  /** CSS Class name for additional styles */
  className?: string;
}

/**
 * Renders an overlay and it's children
 * @example
 * <Modal isShown={true} onBackDropClicked={() => console.log('back-drop clicked')}>
 *  <div>Component(s) to render</div>
 * </Modal>
 */
export const Modal: React.FC<ModalProps> = ({
  isShown,
  children,
  paddingTop,
  paddingRight,
  paddingBottom,
  paddingLeft,
  width,
  zIndex,
  onOpen = noop,
  onClose = noop,
  onBackDropClicked = noop,
  className = '',
}) => {
  const [applyHideStyles, setApplyHideStyles] = useState<boolean>(false);
  const [isFullyOpen, setIsFullyOpen] = useState<boolean>(false);

  const customStyles = {
    paddingTop,
    paddingRight,
    paddingBottom,
    paddingLeft,
    zIndex,
  } as React.CSSProperties;

  const childCustomStyles = {
    width,
  } as React.CSSProperties;

  return (
    <div
      className={clsx(
        classes.container,
        isShown && classes.show,
        applyHideStyles && classes.hide,
        'modal-container',
        className,
      )}
      onClick={() => isShown && onBackDropClicked()}
      style={customStyles}
    >
      <TransitionGroup>
        {isShown && (
          <CSSTransition
            key="modal"
            timeout={200}
            classNames={{
              enter: classes.enter,
              enterDone: classes.enterDone,
              exit: classes.exit,
              exitActive: classes.exitActive,
            }}
            onEnter={() => setApplyHideStyles(false)}
            onEntered={() => {
              setIsFullyOpen(true);
              onOpen();
            }}
            onExit={() => {
              setIsFullyOpen(false);
              setApplyHideStyles(true);
            }}
            onExited={onClose}
          >
            <div
              className={classes.child}
              onClick={(event) => event.stopPropagation()}
              style={childCustomStyles}
              data-test-id="modal"
              data-test-state={isFullyOpen ? 'open' : 'closed'}
            >
              {children}
            </div>
          </CSSTransition>
        )}
      </TransitionGroup>
    </div>
  );
};
