import { useState, useEffect, useRef } from 'react'

interface ITimer {
  tickPeriod?: number
}

interface ITimerHandler {
  running: boolean
  time: number
  intTime: number
  start: () => void
  stop: () => void
  reset: () => void
  setTime: (value: number) => void
}

interface ITimeoutRef {
  current: ReturnType<typeof setTimeout> | undefined
}

export const useTimer = (args?: ITimer): [number, ITimerHandler] => {
  const { tickPeriod } = { tickPeriod: 100, ...args }

  const [running, setRunning] = useState(false)
  const [time, setTime] = useState(0)
  const [intTime, setIntTime] = useState(0)

  const timeout: ITimeoutRef = useRef()
  const lastTick = useRef(Date.now())
  const timeBuffer = useRef(0)

  useEffect(() => {
    if (!running) return
    timeout.current = setTimeout(tick, tickPeriod - timeBuffer.current)
    timeBuffer.current = 0
  }, [time, running])

  function tick() {
    const elapsedTime = Date.now() - lastTick.current
    lastTick.current = Date.now()
    const newTime = (time * 1000 + elapsedTime) / 1000
    setTime(newTime)
    setIntTime(Math.ceil(newTime))
  }

  function start() {
    console.log('start')
    lastTick.current = Date.now()
    setRunning(true)
  }

  function stop() {
    console.log('stop')
    if (timeout.current) clearTimeout(timeout.current)
    timeBuffer.current = Date.now() - lastTick.current
    setRunning(false)
  }

  function reset() {
    setTime(0)
  }

  const handler = {
    running,
    time,
    intTime,
    start,
    stop,
    reset,
    setTime
  }

  return [intTime, handler]
}
