import { clsx } from 'clsx';
import { ReactNode, useContext, useId, useRef } from 'react';
import { CSSTransition } from 'react-transition-group';
import { useIntl } from 'react-intl';

import {
  Size,
  Position,
  PositionTop,
  PositionCenter,
  Scroll,
  CommonProps,
  SizeSmall,
  SizeMedium,
  SizeLarge,
  SizeExtraLarge,
  ScrollContent,
  ScrollViewport,
  Typography,
} from '../common';
import { useLayout } from '../common/hooks';
import Dimmer from '../dimmer';
import Drawer from '../drawer';
import { OverlayIdContext } from '../provider/overlay/OverlayIdProvider';
import Title from '../title/Title';
import { Cross } from '@transferwise/icons';
import IconButton from '../iconButton';
import closeBtnMessages from '../common/closeButton/CloseButton.messages';

const TRANSITION_DURATION_IN_MILLISECONDS = 150;

export type ModalProps = CommonProps & {
  title?: ReactNode;
  body: ReactNode;
  footer?: ReactNode;
  size?: SizeSmall | SizeMedium | SizeLarge | SizeExtraLarge;
  onClose: () => void;
  onUnmount?: () => void;
  open: boolean;
  scroll?: ScrollContent | ScrollViewport;
  position?: PositionTop | PositionCenter;
  disableDimmerClickToClose?: boolean;
};

const Modal = ({
  title = null,
  body,
  footer = null,
  onClose,
  onUnmount,
  className,
  open,
  size = Size.MEDIUM,
  scroll = Scroll.VIEWPORT,
  position = Position.CENTER,
  disableDimmerClickToClose = false,
  ...otherProps
}: ModalProps) => {
  const intl = useIntl();
  const { isMedium } = useLayout();

  const contentReference = useRef<HTMLDivElement>(null);
  const titleId = useId();

  const overlayId = useContext(OverlayIdContext);

  return !isMedium ? (
    <Drawer
      open={open}
      className={className}
      headerTitle={title}
      footerContent={footer}
      position={Position.BOTTOM}
      onClose={onClose}
      onUnmount={onUnmount}
    >
      {body}
    </Drawer>
  ) : (
    <Dimmer
      open={open}
      scrollable={scroll === Scroll.VIEWPORT}
      contentPosition={position}
      disableClickToClose={disableDimmerClickToClose}
      onClose={onClose}
      onExited={onUnmount}
    >
      <CSSTransition
        nodeRef={contentReference}
        appear
        in={open}
        classNames={{ enterDone: 'in' }}
        timeout={TRANSITION_DURATION_IN_MILLISECONDS}
        unmountOnExit
      >
        <div
          ref={contentReference}
          className={clsx(
            'tw-modal',
            'd-flex',
            'fade',
            'outline-none',
            scroll === Scroll.CONTENT && 'tw-modal--scrollable',
            className,
          )}
          {...otherProps}
        >
          <div
            id={overlayId}
            role="dialog"
            aria-modal
            aria-labelledby={titleId}
            className={clsx('tw-modal-dialog', 'd-flex', {
              [`tw-modal-${size}`]: size,
            })}
          >
            <div
              className={clsx(
                'tw-modal-content',
                'd-flex',
                'flex-column',
                'justify-content-between',
              )}
            >
              <div
                className={clsx(
                  'tw-modal-header',
                  'd-flex',
                  'align-items-center',
                  title ? 'justify-content-between' : 'justify-content-end',
                  'flex-wrap',
                )}
              >
                {title && (
                  <Title id={titleId} type={Typography.TITLE_SUBSECTION} className="tw-modal-title">
                    {title}
                  </Title>
                )}
                <IconButton
                  size={40}
                  priority="tertiary"
                  aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}
                  onClick={onClose}
                >
                  <Cross />
                </IconButton>
              </div>
              <div
                className={clsx('tw-modal-body', {
                  'tw-modal-body--scrollable': scroll === Scroll.CONTENT,
                })}
              >
                {body}
              </div>
              {footer ? (
                <div
                  className={clsx('tw-modal-footer', 'd-flex', 'align-items-center', 'flex-wrap')}
                >
                  {footer}
                </div>
              ) : (
                <div className="m-t-3" />
              )}
            </div>
          </div>
        </div>
      </CSSTransition>
    </Dimmer>
  );
};

export default Modal;
