import { useLayoutEffect, useCallback, useRef, RefObject } from 'react';

/**
 * Watch for changes on an element an
 * @param ref - element to watch for resizes
 * @param callback - tallback to trigger when the element resizes
 * @returns
 */
export const useIntersectionObserver = (
    ref: RefObject<HTMLElement>,
    callback: () => void,
    options?: IntersectionObserverInit,
): void => {
    const isIntersecting = useRef(false);

    /**
     * Handle intersection
     */
    const handleIntersection = useCallback(
        (entries: IntersectionObserverEntry[]) => {
            if (!Array.isArray(entries)) {
                return;
            }

            const entry = entries[0];

            // only trigger the callback if it is intersecting and has changed
            if (entry.isIntersecting && !isIntersecting.current) {
                callback();
            }

            // save the old one
            isIntersecting.current = entry.isIntersecting;
        },
        [callback],
    );

    useLayoutEffect(() => {
        if (!ref.current) {
            return;
        }

        let observer: IntersectionObserver | null = new IntersectionObserver(
            (entries: IntersectionObserverEntry[]) =>
                handleIntersection(entries),
            options,
        );
        observer.observe(ref.current);

        return () => {
            if (observer) {
                observer.disconnect();
            }
            observer = null;
            isIntersecting.current = false;
        };
    }, [ref, options, handleIntersection]);
};
