import { type Dispatch, type SetStateAction, useEffect, useState } from "react"

// Ref: https://usehooks.com/useDebounce/
export const useDebounce = <T extends string | number | object>(
  value: T,
  delay = 500
): [T, Dispatch<SetStateAction<T>>] => {
  // State and setters for debounced value
  const [debouncedValue, setDebouncedValue] = useState(value)

  useEffect(
    () => {
      // Update debounced value after delay
      const handler = setTimeout(() => {
        setDebouncedValue(value)
      }, delay)

      // Cancel the timeout if value changes (also on delay change or unmount)
      // This is how we prevent debounced value from updating if value is changed ...
      // .. within the delay period. Timeout gets cleared and restarted.
      return () => {
        clearTimeout(handler)
      }
    },
    [value, delay] // Only re-call effect if value or delay changes
  )

  return [debouncedValue, setDebouncedValue]
}
