import { useCallback, useEffect, useRef, useState } from "react";
const TOOLTIP_TARGET_ELEMENT = 'tooltip-target-element';
function getLineClamp(computedStyle) {
    return computedStyle.getPropertyValue('-webkit-line-clamp') || computedStyle.WebkitLineClamp;
}
function hasLineClamp(computedStyle) {
    const lineClamp = getLineClamp(computedStyle);
    return Boolean(lineClamp && 'none' !== lineClamp);
}
function isTruncationStyleCandidate(element) {
    const computedStyle = window.getComputedStyle(element);
    return 'ellipsis' === computedStyle.textOverflow || hasLineClamp(computedStyle);
}
function findTruncationStyleCandidate(element) {
    if (!(element instanceof HTMLElement)) return;
    if (isTruncationStyleCandidate(element)) return element;
    return Array.from(element.children).find((child)=>child instanceof HTMLElement && isTruncationStyleCandidate(child));
}
function useTruncationDetection(elementRef) {
    const [isTruncated, setIsTruncated] = useState(false);
    const hasCheckedRef = useRef(false);
    const resizeObserverRef = useRef(null);
    const checkTruncation = useCallback(()=>{
        const element = elementRef.current;
        if (!element || !(element instanceof HTMLElement)) return void setIsTruncated(false);
        let targetElement = element;
        if (element.id === TOOLTIP_TARGET_ELEMENT) {
            const slot = element.querySelector('slot');
            if (slot) {
                const assignedNodes = slot.assignedNodes();
                for (const node of assignedNodes)if (node.nodeType === Node.ELEMENT_NODE) {
                    targetElement = node;
                    break;
                }
            } else if (element.firstElementChild) targetElement = element.firstElementChild;
            if (targetElement.id === TOOLTIP_TARGET_ELEMENT) {
                const rootNode = element.getRootNode();
                if (rootNode instanceof ShadowRoot) {
                    const hostElement = rootNode.host;
                    const slottedElement = findTruncationStyleCandidate(hostElement.querySelector('div[data-slot-name="children"]')) || Array.from(hostElement.children).map((child)=>findTruncationStyleCandidate(child)).find(Boolean);
                    if (slottedElement instanceof HTMLElement) targetElement = slottedElement;
                }
            }
        }
        const computedStyle = window.getComputedStyle(targetElement);
        const isLineClamped = hasLineClamp(computedStyle);
        const hasEllipsis = 'ellipsis' === computedStyle.textOverflow;
        const hasOverflowHidden = 'hidden' === computedStyle.overflow || 'hidden' === computedStyle.overflowX;
        const hasWhiteSpaceNowrap = 'nowrap' === computedStyle.whiteSpace;
        if (isLineClamped) return void setIsTruncated(targetElement.scrollHeight > targetElement.clientHeight);
        if (!hasEllipsis || !hasOverflowHidden || !hasWhiteSpaceNowrap) return void setIsTruncated(false);
        const isElementTruncated = targetElement.scrollWidth > targetElement.clientWidth;
        setIsTruncated(isElementTruncated);
    }, [
        elementRef
    ]);
    const setupObservers = useCallback(()=>{
        if (hasCheckedRef.current) return;
        const element = elementRef.current;
        if (!element) return;
        hasCheckedRef.current = true;
        if (!resizeObserverRef.current) {
            resizeObserverRef.current = new ResizeObserver(checkTruncation);
            resizeObserverRef.current.observe(element);
            if (element.id === TOOLTIP_TARGET_ELEMENT && element.firstElementChild) resizeObserverRef.current.observe(element.firstElementChild);
        }
        window.addEventListener('resize', checkTruncation);
    }, [
        checkTruncation,
        elementRef
    ]);
    const check = useCallback(()=>{
        checkTruncation();
        setupObservers();
    }, [
        checkTruncation,
        setupObservers
    ]);
    useEffect(()=>()=>{
            if (resizeObserverRef.current) {
                resizeObserverRef.current.disconnect();
                resizeObserverRef.current = null;
            }
            window.removeEventListener('resize', checkTruncation);
        }, [
        checkTruncation
    ]);
    return {
        isTruncated,
        check
    };
}
export { useTruncationDetection };
