import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';
import React, { CSSProperties, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { gray200 } from '../styles/colors';

const fadeIn = keyframes`
  0% { opacity: 0; }
  100% { opacity: 1; }
`;

const fadeUp = keyframes`
  0% { opacity: 0; transform: translateY(20px); }
  100% { opacity: 1; transform: translateY(0px); }
`;

const ModalWrapper = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 13;
  animation: ${fadeIn} 0.3s;
`;

const ModalContent = styled.div`
  color: white;
  background-color: ${gray200};
  max-height: 100svh;
  overflow-y: scroll;
  animation: ${fadeUp} 0.3s;
`;

const ModalHeader = styled.div`
  padding: 20px 20px 0 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
`;

const ModalTitle = styled.div<{ center?: boolean }>`
  font-size: 25px;
  color: inherit;
  text-align: ${({ center }) => (center ? 'center' : 'left')};
  width: ${({ center }) => (center ? '100%' : 'auto')};
`;

const ModalBody = styled.div`
  padding: 15px 20px 20px 20px;
`;

const ModalCloseButton = styled.button`
  background: transparent;
  border: none;
  color: inherit;
  font-size: 30px;
  font-weight: 100;
  margin-left: 20px;
  margin-top: -3px;
  transform: scale(1.25);
  transform-origin: 50% 50%;
  &:hover {
    cursor: pointer;
  }
  &:after {
    margin-top: -10px;
    display: inline-block;
    content: '×';
  }
`;

// I expect to reuse this a lot.
export const ModalFooter = styled.div`
  display: flex;
  justify-content: space-between;
  margin-top: 20px;
`;

export interface ModalProps {
  open: Boolean;
  onClose: () => void;
  title?: string;
  children: React.ReactNode[] | React.ReactNode;
  style?: CSSProperties;
  bodyStyle?: CSSProperties;
  wrapperStyle?: CSSProperties;
  hideCloseButton?: boolean;
  belowContent?: React.ReactNode;
}

// open is a required argument. conditional rendering bad.
const Modal = ({
  open,
  onClose,
  title,
  children,
  hideCloseButton,
  style,
  bodyStyle,
  wrapperStyle,
  belowContent,
}: ModalProps) => {
  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (open && e.key === 'Escape') {
        onClose();
      }
    };
    window.addEventListener('keydown', handleEscape);
    return () => {
      window.removeEventListener('keydown', handleEscape);
    };
  }, [onClose, open]);

  if (!open) {
    return null;
  }

  return createPortal(
    <ModalWrapper style={wrapperStyle} onClick={(e) => e.target === e.currentTarget && onClose()}>
      <ModalContent style={style}>
        {(Boolean(title) || !hideCloseButton) && (
          <ModalHeader>
            <ModalTitle center={hideCloseButton}>{title}</ModalTitle>
            {!hideCloseButton && <ModalCloseButton onClick={onClose} />}
          </ModalHeader>
        )}
        <ModalBody style={bodyStyle}>{children}</ModalBody>
      </ModalContent>
    </ModalWrapper>,
    document.body
  );
};

export default Modal;
