import React, {
  FC,
  ReactNode,
  RefObject,
  useEffect,
  useRef,
  useState
} from 'react'

import {
  appendVariantClasses,
  formatClassList,
  joinStrings
} from '../../utils'


type ToastTypes = {
  className?: string,
  dismissAfter?: number,
  variant?: string,
  title?: string,
  children: ReactNode,
  [other:string]: unknown 
}

const TOAST: string = `
  border-l-4
  font-sans
  overflow-hidden
  p-4
  relative
  rounded-sm
  shadow-md
  transition-all
  duration-300
  ease-in-out
`

const TIME: string = `
  absolute
  bottom-0
  float-right
  inline-block
  right-0
  rounded-bottom
`

const WRAPPER: string = `
  fixed
  top-0
  mt-10
  mr-10
  right-0
  sm:max-w-md
  z-50
`

const CLOSE_ICON: string = `
  absolute
  cursor-pointer
  fa-times
  fas
  focus:outline-none
  focus:shadow-outline
  m-2
  right-0
  text-2xl
  top-0
`

const RED_TIME: string = `
  bg-bscs-red-800
`

const YELLOW_TIME: string = `
  bg-bscs-yellow-800
`

const GREEN_TIME: string = `
  bg-bscs-green-800
`

const INDIGO_TIME: string = `
  bg-bscs-indigo-800
`

const RED: string = `
  bg-bscs-red-100
  border-bscs-red-800
  text-bscs-red-800
`

const YELLOW: string = `
  bg-bscs-yellow-200
  border-bscs-yellow-800
  text-bscs-yellow-800
`
const GREEN: string = `
  bg-bscs-green-100
  border-bscs-green-800
  text-bscs-green-800
`

const INDIGO: string = `
  bg-bscs-indigo-100
  border-bscs-indigo-800
  text-bscs-indigo-800
`

const RED_ICON: string = `
  fa-exclamation-circle
  fas
  mr-3
  text-base
`

const YELLOW_ICON: string = `
  fa-exclamation-triangle
  fas
  mr-3
  text-base
`

const GREEN_ICON: string = `
  fa-check-circle
  fas
  mr-3
  text-base
`

const INDIGO_ICON: string = `
  fa-info-circle
  fas
  mr-3
  text-base
`

const VARIANTS: Record<string, string> = {
  'green': GREEN,
  'indigo': INDIGO,
  'red': RED,
  'yellow': YELLOW
}

const ICON_VARIANTS: Record<string, string> = {
  'green': GREEN_ICON,
  'indigo': INDIGO_ICON,
  'red': RED_ICON,
  'yellow': YELLOW_ICON
}

const TIME_VARIANTS: Record<string, string> = {
  'green': GREEN_TIME,
  'indigo': INDIGO_TIME,
  'red': RED_TIME,
  'yellow': YELLOW_TIME
}

const hideWrapper = (ref: RefObject<HTMLDivElement> | null): void => {
  setTimeout(() => {
    if (!ref || !ref.current) {
      return
    }

    ref.current.style.display = 'none'
  }, 300)
}

const Toast:FC<ToastTypes> = ({
  className,
  children,
  dismissAfter=5,  
  title,
  variant='indigo',
  ...other
}: ToastTypes) => {
  const [show, setShow] = useState(true)
  const [timeElapsed, setTimeElapsed] = useState(0)

  const wrapperRef: RefObject<HTMLDivElement> | null = useRef<HTMLDivElement>(null)

  variant = variant.toLowerCase()

  const classList: string = formatClassList(
    appendVariantClasses(TOAST, VARIANTS, variant)
  )
  
  const closeIconClassList: string = formatClassList(CLOSE_ICON)
  
  const iconClassList: string = formatClassList(
    appendVariantClasses('', ICON_VARIANTS, variant)
  )
  
  const timeClassList: string = formatClassList(
    appendVariantClasses(TIME, TIME_VARIANTS, variant)
  )
  
  const wrapperClassList: string = formatClassList(WRAPPER)

  useEffect(() => {
    const timer = setInterval(() => {
      setTimeElapsed(timeElapsed => {
        if ((timeElapsed + 10) / 1000 === dismissAfter) {
          clearInterval(timer)
          setShow(false)
          hideWrapper(wrapperRef)
        }
        
        return timeElapsed + 10
      })
    }, 10)

    return () => {
      clearInterval(timer)
    }
  // eslint-disable-next-line
  }, [])

  return (
    <div
      className={
        className
          ? joinStrings(' ', wrapperClassList, className)
          : wrapperClassList
      }
      ref={wrapperRef}
      role="alert"
      {...other}
    >
      <div
        className={classList}
        style={{
          marginLeft: show ? '0rem' : '100rem',
          marginRight: show ? '0rem' : '-100rem',
        }}
      >
        <div className="flex mr-2">
          <i className={iconClassList} />
          <div>
            <p className="text-sm font-bold uppercase">{title}</p>
            <p className="mt-1 leading-tight tracking-wider text-base">
              {children}
            </p>
          </div>
        </div>
        <button
          className={closeIconClassList}
          onClick={() => setShow(false)}
        />
        <div
          className={timeClassList}
          style={{
            height: '4px',
            width: `${(dismissAfter - timeElapsed / 1000) / dismissAfter * 100}%`
          }}
        />
      </div>
    </div>
  )
}

export default Toast
