import { ReactNode, RefObject } from 'react'
import { Notify, NotifyProps, NotifyImperative } from './Notify'
import { isNotReactNode, imperative, AgentComponentRef } from '../../utils'

export interface NotifyShortcutMethod {
  (propsOrMessage: ReactNode | NotifyProps, props?: NotifyProps): void
}

export interface NotifyShowMethod {
  (
    propsOrTitle: ReactNode | NotifyProps,
    props?: NotifyProps,
    innerType?: NotifyProps['type']
  ): void
}

let agentComponentRef: RefObject<
  AgentComponentRef<NotifyProps, NotifyImperative>
>

let cacheProps: NotifyProps

export const show: NotifyShowMethod = (
  propsOrMessage,
  props = {},
  innerType
) => {
  if (isNotReactNode(propsOrMessage)) {
    props = propsOrMessage as NotifyProps 
  } else {
    props.message = propsOrMessage as ReactNode
  }

  if (innerType) {
    props.type = innerType
  }

  cacheProps = props

  if (!agentComponentRef) {
    agentComponentRef = imperative<NotifyProps, NotifyImperative>(
      ({ ref, container }) => ({
        component: Notify,
        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 info: NotifyShortcutMethod = (propsOrMessage, props) => {
  show(propsOrMessage, props, 'info')
}

export const success: NotifyShortcutMethod = (propsOrMessage, props) => {
  show(propsOrMessage, props, 'success')
}

export const warning: NotifyShortcutMethod = (propsOrMessage, props) => {
  show(propsOrMessage, props, 'warning')
}

export const error: NotifyShortcutMethod = (propsOrMessage, props) => {
  show(propsOrMessage, props, 'error')
}

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