import * as React from 'react';
import ResizeObserver from 'resize-observer-polyfill';

const throttleResize = (
  callback: ResizeObserverCallback,
  ms: number,
): ResizeObserverCallback => {
  let timeoutID: number | null = null;

  return (...args: [ResizeObserverEntry[], ResizeObserver]) => {
    if (timeoutID !== null) {
      return;
    }

    timeoutID = setTimeout(() => {
      callback(...args);

      timeoutID = null;
    }, ms);
  };
};

/* global ResizeObserverCallback */
export default function useResizeObserver(
  onChange: ResizeObserverCallback,
  throttleTimeoutMS?: number,
) {
  const [ref, setRef] = React.useState<HTMLElement | null>(null);
  const observer = React.useMemo(
    () =>
      new ResizeObserver(
        throttleTimeoutMS === undefined
          ? onChange
          : throttleResize(onChange, throttleTimeoutMS),
      ),
    [onChange],
  );

  React.useEffect(() => {
    return () => {
      // If the observer changes, make sure to clean up the old one.
      observer.disconnect();
    };
  }, [observer]);

  React.useEffect(() => {
    if (!ref) return;
    observer.observe(ref);
    return () => {
      observer.unobserve(ref);
    };
  }, [observer, ref]);

  return setRef;
}
