import { ReactNode, RefObject } from 'react'
import { Toast, ToastProps, ToastImperativeHandle } from './Toast'
import { isNotReactNode, imperative, AgentComponentRef } from '../../utils'

export interface ToastShortcutMethod {
  (propsOrTitle: ReactNode | ToastProps, props?: ToastProps): void
}

export interface ToastShowMethod {
  (
    propsOrTitle: ReactNode | ToastProps,
    props?: ToastProps,
    internalType?: ToastProps['type']
  ): void
}

let agentComponentRef: RefObject<
  AgentComponentRef<ToastProps, ToastImperativeHandle>
>

let cacheProps: ToastProps

export const show: ToastShowMethod = (
  propsOrTitle,
  props = {},
  internalType = 'custom'
) => {
  if (isNotReactNode(propsOrTitle)) {
    props = propsOrTitle as ToastProps
  } else {
    props.title = propsOrTitle as ReactNode
  }

  if (internalType) {
    props.type = internalType
  }

  cacheProps = props

  if (!agentComponentRef) {
    agentComponentRef = imperative<ToastProps, ToastImperativeHandle>(
      ({ ref, container }) => ({
        component: Toast,
        baseProps: {
          onTimeout() {
            ref.current?.$$setProps({
              visible: false,
            })
            cacheProps.onTimeout?.()
          },
          popupProps: {
            container,
          },
        },
        props: cacheProps,
        afterRender() {
          ref.current?.$$setProps({
            visible: true,
          })
        },
      })
    )
  } else {
    agentComponentRef.current?.reset()
    agentComponentRef.current?.$$setProps(
      {
        ...cacheProps,
        visible: true,
      },
      true
    )
  }
}

export const text: ToastShortcutMethod = (propsOrTitle, props) => {
  show(propsOrTitle, props, 'text')
}

export const success: ToastShortcutMethod = (propsOrTitle, props) => {
  show(propsOrTitle, props, 'success')
}

export const fail: ToastShortcutMethod = (propsOrTitle, props) => {
  show(propsOrTitle, props, 'fail')
}

export const loading: ToastShortcutMethod = (propsOrTitle, props) => {
  show(propsOrTitle, props, 'loading')
}

export const hide = () => {
  agentComponentRef?.current?.$$setProps({
    visible: false,
  })
}
