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

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

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

export const useTimer = (tickPeriod = 1000): [number, ITimerHandler] => {
  const [running, setRunning] = useState(false)
  const [time, setTime] = useState(0)

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

  useEffect(() => {
    if (!running) return
    const delta = time - Math.round(time)
    console.log('new timeout', tickPeriod - timeBuffer.current - delta * 1000)
    timeout.current = setTimeout(tick, tickPeriod - timeBuffer.current - delta * 1000)
    timeBuffer.current = 0
  }, [time, running])

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

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

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

  function reset() {
    setTime(0)
  }

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

  return [time, handler]
}
