export type ToastType = 'success' | 'error' | 'info' | 'warning'

export interface ToastItem {
  id: number
  type: ToastType
  message: string
  duration: number
}

type Listener = (items: ToastItem[]) => void

let seq = 1
let items: ToastItem[] = []
const listeners = new Set<Listener>()

function emit() {
  listeners.forEach((fn) => fn([...items]))
}

function push(type: ToastType, message: string, duration = 3000) {
  const id = seq++
  const item: ToastItem = { id, type, message, duration }
  items = [...items, item]
  emit()
  if (duration > 0) {
    window.setTimeout(() => {
      dismiss(id)
    }, duration)
  }
  return id
}

export function dismiss(id: number) {
  items = items.filter((t) => t.id !== id)
  emit()
}

export function subscribeToast(listener: Listener) {
  listeners.add(listener)
  listener([...items])
  return () => {
    listeners.delete(listener)
  }
}

export const toast = {
  success: (message: string, duration?: number) => push('success', message, duration),
  error: (message: string, duration?: number) => push('error', message, duration ?? 4000),
  info: (message: string, duration?: number) => push('info', message, duration),
  warning: (message: string, duration?: number) => push('warning', message, duration),
}
