import React from 'react';

const useOnResize = (
  ref: React.MutableRefObject<HTMLIFrameElement | null>,
  onResize: () => void,
) => {
  const getTarget = () =>
    ref.current &&
    ref.current.contentDocument &&
    ref.current.contentDocument.defaultView;
  function run() {
    // trigger onResize event on mount to provide initial sizes
    onResize();
    const target = getTarget();
    target && target.addEventListener('resize', onResize);
  }
  React.useEffect(() => {
    if (getTarget()) {
      run();
    } else if (ref.current && ref.current.addEventListener) {
      ref.current.addEventListener('load', run);
    }

    // clean event listener on unmount
    return () => {
      // Ensure the target exists and is in fact an event listener
      // this fixes an issue where contentDocument.defaultView is not a real window object
      // as can be the case when used with React portals
      const target = getTarget();
      const isListener =
        target && typeof target.removeEventListener === 'function';

      isListener && target.removeEventListener('resize', onResize);
    };
  }, []);
};

const style = {
  display: 'block',
  opacity: 0,
  position: 'absolute',
  top: 0,
  left: 0,
  height: '100%',
  width: '100%',
  overflow: 'hidden',
  pointerEvents: 'none',
  zIndex: -1,
  maxHeight: 'inherit',
  maxWidth: 'inherit',
} as any;

const ResizeListener = ({ onResize }) => {
  const ref = React.useRef<HTMLIFrameElement | null>(null);
  useOnResize(ref, () => onResize(ref));

  return (
    <iframe
      style={style}
      src="about:blank"
      ref={ref}
      // aria-hidden={true}
      tabIndex={-1}
      frameBorder={0}
    />
  );
};

const defaultReporter = (target: HTMLElement | null) => ({
  width: target != null ? target.offsetWidth : null,
  height: target != null ? target.offsetHeight : null,
});

export default function useResizeAware(
  reporter: typeof defaultReporter = defaultReporter,
) {
  const [sizes, setSizes] = React.useState(reporter(null));
  const onResize = React.useCallback(
    (ref) => setSizes(reporter(ref.current)),
    [reporter],
  );
  const resizeListenerNode = React.useMemo(() => {
    return <ResizeListener onResize={onResize} />;
  }, [onResize]);

  return [resizeListenerNode, sizes];
}
