import { useState, useLayoutEffect, useCallback } from 'react';
import { windowIsAvailable, debounce } from '../utils';
import useChToPxConversionFactor from './useChToPxConversionFactor';
import useTheme from './useTheme';
// We should be able to safely capture once as the computed root font size is unlikely to change during normal runtime.
const rootFontSize = windowIsAvailable
    ? window.getComputedStyle(document.documentElement).fontSize
    : '16px';
/**
 * @example const breakpointActive = useBreakpoint(breakpoint);
 * @param breakpoint The string indicator for the breakpoint that should be checked for validity.
 * @param options
 * @returns breakpointActive:: A boolean indicating if the given breakpoint is active or not. If false, the breakpoint is too big for the screen size.
 */
const useBreakpoint = (breakpoint, { breakpointRef, defaultValue = false, themeProp = 'breakpoints' } = {}) => {
    const { base: { breakpoints, 'content-width': contentWidth } } = useTheme();
    const breakpointVal = themeProp === 'content-width' ? contentWidth[breakpoint] : breakpoints[breakpoint];
    const [matches, setMatches] = useState(windowIsAvailable ? window.matchMedia(`(min-width: ${breakpointVal})`).matches : !!defaultValue);
    const chToPxConversionFactor = useChToPxConversionFactor();
    const onResize = useCallback((e) => {
        setMatches(e.matches);
    }, []);
    useLayoutEffect(() => {
        // Breakpoint handling for contained elements
        if (breakpointRef && breakpointRef.current) {
            const debouncedResize = debounce((entries) => {
                if (!breakpointRef.current?.checkVisibility())
                    return;
                const matchesBreakpoint = entries.some(({ target, contentRect }) => {
                    if (target !== breakpointRef.current)
                        return;
                    const multiplier = themeProp === 'breakpoints' ? parseFloat(rootFontSize) : chToPxConversionFactor;
                    return contentRect.width >= parseFloat(breakpointVal) * multiplier;
                });
                setMatches(matchesBreakpoint);
            }, 100);
            const observer = new ResizeObserver(debouncedResize);
            observer.observe(breakpointRef.current);
            return () => {
                observer.disconnect();
            };
        }
        // Breakpoint handling for viewport
        if (windowIsAvailable) {
            const mediaMatch = window.matchMedia(`(min-width: ${breakpointVal})`);
            const mediaMatchAvailable = 'addEventListener' in mediaMatch;
            const resizeHandler = debounce(() => {
                setMatches(window.innerWidth >= parseInt(breakpointVal, 10));
            }, 100);
            // Need to check useMatchMedia in order to support unit testing
            if (mediaMatchAvailable) {
                mediaMatch.addEventListener('change', onResize);
                setMatches(mediaMatch.matches);
            }
            else {
                window.addEventListener('resize', resizeHandler);
                setMatches(window.innerWidth >= parseInt(breakpointVal, 10));
            }
            return () => {
                // Need to check useMatchMedia in order to support unit testing
                if (mediaMatchAvailable)
                    mediaMatch.removeEventListener('change', onResize);
                else {
                    window.removeEventListener('resize', resizeHandler);
                }
            };
        }
    }, [breakpointRef?.current]);
    return matches;
};
export default useBreakpoint;
//# sourceMappingURL=useBreakpoint.js.map