import { useCallback, useEffect, useRef } from "react"

/**
 * Calls the function `debounce` milliseconds after the last time the function
 * is called (trailing debounce). Any change to deps will reset the timer, not
 * calling the function.
 *
 * @param {function} callback
 * @param {integer} debounce
 * @param {array} deps
 */
const useDebounce = (callback, debounce) => {
  const timeout = useRef()
  const cb = useRef()

  useEffect(() => {
    cb.current = callback
  }, [callback])

  const cancel = useCallback(() => {
    clearTimeout(timeout.current)
  }, [timeout.current])

  useEffect(() => {
    cancel()
  }, [debounce])

  const debounced = useCallback(
    (...args) => {
      cancel()

      timeout.current = setTimeout(() => {
        cb.current(...args)
      }, debounce)
    },
    [debounce]
  )

  return [debounced, cancel]
}

export default useDebounce
