import React, { Component } from 'react'
import classNames from 'classnames'

type Props = Readonly<{
  children: (props: any) => any
  className?: string | null
}>

type Notify = Readonly<{
  id?: string
  title: string
  text: string
  kind: string
}>

type State = Readonly<{
  messages: Notify[] | null
}>

export default class Notifications extends Component<Props, State> {
  state = {
    messages: [],
  }

  dismiss = (messageID: string) => {
    const { messages: currentMessages } = this.state
    const messages = [...currentMessages]
    this.setState({
      messages: messages.filter(({ id }) => id !== messageID),
    })
  }

  notify = ({
    id = Math.random().toString(16).substr(2),
    title,
    text,
    kind,
  }: Notify) => {
    const { messages: currentMessages } = this.state
    const messages: Notify[] = [...currentMessages]
    messages.push({ id, title, text, kind })
    this.setState({ messages })
    setTimeout(
      (
        (messageID) => () =>
          this.dismiss(messageID)
      )(id),
      5000
    )
  }

  render() {
    const { messages } = this.state
    const { children, className } = this.props
    return (
      <>
        <div
          className={classNames(
            'ui-notification-container ui-position--fixed ui-position--upper-right ui-p--2',
            className
          )}
        >
          {messages.map(({ id, title, text, kind }, i) => (
            <div
              key={`notification-${id}`}
              id={`notification-${i}`}
              className={classNames(
                'ui-notification ui-notification--animate ui-animate ui-bg__paper--supreme ui-p--1 ui-border ui-border--light ui-border-radius ui-mb--1',
                {
                  'ui-notification--danger': kind === 'danger',
                  'ui-notification--success': kind === 'success',
                }
              )}
            >
              {title && (
                <strong className="ui-notification__title ui-text__label ui-text__label--md ui-display--block">
                  {title}
                </strong>
              )}
              {text}
            </div>
          ))}
        </div>
        {children(this.notify)}
      </>
    )
  }
}
