import moment from 'moment'

type RTimeElement = HTMLElement & { _next_timer?: number }

const parseInterval = (arg: string | undefined): number => {
  if (!arg) {
    return 60 * 1000
  }

  const match = arg.match(/^(\d+)([smhd])$/)

  if (!match) {
    return 60 * 1000
  }

  const [, numStr, unit] = match
  const num = parseInt(String(numStr), 10)

  switch (unit) {
    case 'd': return num * 24 * 3600 * 1000
    case 'h': return num * 3600 * 1000
    case 'm': return num * 60 * 1000
    case 's': return num * 1000
    default: return 60 * 1000
  }
}

export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.vueApp.directive('rtime', {
    mounted(el: RTimeElement, binding) {
      const intervalMs = parseInterval(binding.arg)
      const update = () => {
        const val = binding.value
        if (Number.isFinite(val)) {
          el.textContent = moment.unix(val as number).fromNow()
          return
        }
        el.textContent = moment(val).fromNow()
      }

      update()
      el._next_timer = window.setInterval(update, intervalMs)
    },
    updated(el: RTimeElement, binding) {
      if (binding.oldValue !== binding.value) {
        if (null != el._next_timer) clearInterval(el._next_timer)

        const intervalMs = parseInterval(binding.arg)
        const update = () => {
          const val = binding.value
          if (Number.isFinite(val)) {
            el.textContent = moment.unix(val as number).fromNow()
            return
          }
          el.textContent = moment(val).fromNow()
        }

        update()
        el._next_timer = window.setInterval(update, intervalMs)
      }
    },
    beforeUnmount(el: RTimeElement) {
      if (null != el._next_timer) clearInterval(el._next_timer)
    }
  })

  return {}
})
