import * as React from 'react';
import cn from 'classnames';
import { usePortal } from 'hooks';
import { Space } from 'components/atoms';
import { SpaceDirection, SpaceSize } from 'components/atoms/Space/Space';

import { NotifyItem, NotifyItemProps } from './NotifyItem';

interface ContextProps {
  list: NotifyItemProps[];
  push: (value: NotifyItemProps) => void;
  remove: (value: number) => void;
}

const NotifyContext = React.createContext<ContextProps>({
  list: [],
  push: () => null,
  remove: () => null,
});

export interface NotifyProps {
  list?: NotifyItemProps[];
  vertical?: 'top' | 'bottom';
  horizontal?: 'left' | 'right';
  direction?: SpaceDirection;
  size?: SpaceSize;
  timeout?: number;
}

const NotifyContainer: React.FC<NotifyProps> = ({
  vertical = 'top',
  horizontal = 'right',
  size = 'medium',
  timeout = 3000,
}) => {
  const createPortal = usePortal('notify-portal');
  const { list, remove } = React.useContext(NotifyContext);

  React.useEffect(() => {
    const interval = setInterval(() => {
      if (list.length) {
        remove(0);
      }
    }, timeout);

    return () => {
      clearInterval(interval);
    };
  }, [list]);

  const position = React.useMemo(() => `${vertical}-${horizontal}`, [vertical, horizontal]);

  const onClose = React.useCallback((i) => remove(i), []);

  return createPortal(
    <Space direction="vertical" size={size} className={cn('ebs-notify', `ebs-notify--${position}`)}>
      {list.map((props, i) => (
        <NotifyItem key={i} size={size} onClose={() => onClose(i)} {...props} />
      ))}
    </Space>,
  );
};

// Provider
const NotifyProvider = ({ children }): React.ReactElement => {
  const [list, setList] = React.useState<NotifyItemProps[]>([]);

  const push = React.useCallback((item: NotifyItemProps) => setList((i) => [...i, item]), [setList]);
  const remove = React.useCallback((i: number) => setList((y) => y.filter((_, x) => x !== i)), [setList]);

  return <NotifyContext.Provider value={{ list, push, remove }}>{children}</NotifyContext.Provider>;
};

export { NotifyContainer, NotifyContext, NotifyProvider };