import throttle from 'lodash/throttle';
import { useCallback, useEffect, useRef } from 'react';

/**
 * Interfaces from Lodash
 * @see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ef8f9bb5ba32fb36ff978ac9898cc4f35cf7a9d6/types/lodash/common/function.d.ts#L1358-L1376
 */

/**
 * A hook which replaces imperative throttle from Lodash and works with React lifecycle
 * @param callback a function, **should** be wrapped in useCallback
 * @param delay in milliseconds
 * @param options check throttle options for description. Hook does not react to change of this object,
 * so it is not required to wrap it in useMemo or define outside component
 * @returns throttled function which has cancel and flush methods, always the same instance of a function.
 * @see https://lodash.com/docs/4.17.15#throttle
 */
export function useThrottle(callback, delay, options) {
  const savedCallback = useRef(throttle(callback, delay, options));
  useEffect(() => {
    savedCallback.current?.cancel();
    savedCallback.current = throttle(callback, delay, options);
    return () => savedCallback?.current?.cancel();
  }, [delay, callback]);
  const resultFunction = useCallback((...args) => savedCallback.current(...args), []);
  if (!resultFunction.cancel) {
    resultFunction.cancel = () => savedCallback.current?.cancel?.();
    resultFunction.flush = () => savedCallback.current?.flush?.();
  }
  return resultFunction;
}