import React from "react"
import PropTypes from "prop-types"
import { CloseIcon, SuccessIcon, ErrorIcon, InfoIcon } from "./assets"
import Button, { ButtonGroup } from "../button"
import VisuallyHidden from "@reach/visually-hidden"

const ICONS = {
  success: SuccessIcon,
  error: ErrorIcon,
  info: InfoIcon,
}

// The convertkit-design build has trouble importing SVGs, so we've formatted
// the default icons as components. On the main app, it's cleaner to import an
// SVG and pass it into an <img src="" />, so we want to support both of these
// use cases. Once ck-design's build supports SVG imports, this can be removed.
const ImageOrSVG = ({ icon, ...rest }) => {
  // If the icon is a React component...
  if (typeof icon === "function") {
    const Icon = icon
    return <Icon {...rest} />
  } else {
    // If the icon is imported...
    return <img src={icon} {...rest} />
  }
}

const getBarColor = (type) => {
  switch (type) {
    case "success":
      return "#589D78"
    case "error":
      return "var(--yellow-500)"
    case "info":
      return "var(--blue-500)"
    case "cta":
    default:
      return "var(--gray-100)"
  }
}

const Icon = ({ type, icon }) => {
  const barStyles = {
    backgroundColor: getBarColor(type),
    borderRadius: 6,
    top: 6,
    left: 6,
    bottom: 6,
    width: 4,
  }

  const iconStyles = {
    width: 26,
    height: 26,
  }

  return (
    <div className="justify-center ml-6 mr-6 hidden md:flex">
      <div className="absolute inset-y-auto left-0" style={barStyles} />
      <ImageOrSVG
        icon={icon || ICONS[type]}
        alt=""
        style={iconStyles}
        className="ml-2"
      />
    </div>
  )
}

const Text = ({ title, text }) => {
  return (
    <div>
      {title && <div className="font-semibold text-gray-900 mb-1">{title}</div>}
      {text && <div className="text-gray-700">{text}</div>}
    </div>
  )
}

const Actions = ({ actions, handleClose }) => (
  <div className="ml-4">
    <ButtonGroup>
      {actions.map((action) => {
        // Closes the toast after an action button is clicked.
        const handleClick = async () => {
          if (!action.onClick) return
          await action.onClick()
          handleClose()
        }

        return (
          <Button
            key={action.text}
            is="primary"
            className="whitespace-no-wrap"
            {...action}
            onClick={handleClick}
          >
            {action.text}
          </Button>
        )
      })}
    </ButtonGroup>
  </div>
)

const Close = ({ handleClose }) => {
  const closeStyles = {
    width: 16,
    height: 16,
  }

  return (
    <button onClick={handleClose} className="absolute top-0 right-0 p-2 block">
      <CloseIcon className="block" style={closeStyles} />
      <VisuallyHidden>Close notification</VisuallyHidden>
    </button>
  )
}

function Toast({
  type = "info",
  title,
  text,
  icon,
  actions,
  handleClose,
  closable,
}) {
  return (
    <div role="alert" className="mx-2 mb-4">
      <div className="rounded bg-white flex items-center text-left relative shadow-lg text-sm p-3 md:pr-8 md:pl-0 md:py-6">
        <Icon type={type} icon={icon} />
        <Text title={title} text={text} />
        {actions && <Actions actions={actions} handleClose={handleClose} />}
        {closable && <Close handleClose={handleClose} />}
      </div>
    </div>
  )
}

Toast.propTypes = {
  text: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType])
    .isRequired,
  type: PropTypes.oneOf(["info", "success", "error", "cta"]).isRequired,
  title: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
  actions: PropTypes.array,
  position: PropTypes.oneOf([
    "bottom",
    "top",
    "top-right",
    "bottom-right",
    "bottom-left",
    "top-left",
  ]),
  duration: PropTypes.number,
  icon: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
  handleClose: PropTypes.func,
  closable: PropTypes.bool,
}

export default Toast
