"""JavaScript generator for dynamic viewport height calculation."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/js/viewport.ipynb.

# %% auto #0
__all__ = ['generate_viewport_height_js']

# %% ../../nbs/js/viewport.ipynb #jv000003
from ..core.html_ids import CardStackHtmlIds

# %% ../../nbs/js/viewport.ipynb #jv000005
def generate_viewport_height_js(
    ids: CardStackHtmlIds,  # HTML IDs for this card stack instance
    container_id: str = "",  # Consumer's parent container ID (empty = use card stack parent)
) -> str:  # JavaScript code fragment for viewport height calculation
    """Generate JS for dynamic viewport height calculation.

    Computes sibling space by subtracting the card stack's current height
    from the container's current height. This avoids layout distortion that
    occurs with collapse-and-measure when the card stack is nested inside
    intermediate flex-grow containers (e.g., dual-column layouts where
    sibling columns keep the container inflated during collapse).
    """
    handler_key = f"_csResizeHandler_{ids.prefix.replace('-', '_')}"

    # Build container resolution logic — guarded against null for SPA navigation
    if container_id:
        container_resolution = f"""
            const container = document.getElementById('{container_id}');"""
    else:
        container_resolution = f"""
            const _csEl = document.getElementById('{ids.card_stack}');
            if (!_csEl) return 400;
            const container = _csEl.parentElement;"""

    return f"""
        // === Viewport Height Calculation ===

        function calculateSpaceBelowContainer(container) {{
            let spaceUsedBelow = 0;
            let currentElement = container;
            let parent = container.parentElement;
            while (parent && parent !== document.documentElement) {{
                const parentStyles = getComputedStyle(parent);
                spaceUsedBelow += parseFloat(parentStyles.paddingBottom) || 0;
                spaceUsedBelow += parseFloat(parentStyles.borderBottomWidth) || 0;

                // Skip sibling heights when parent uses horizontal flex layout
                // (siblings are side-by-side, not stacked vertically).
                // Uses computed style so responsive breakpoints (e.g. lg:flex-row)
                // are handled automatically.
                const flexDir = parentStyles.flexDirection;
                const isHorizontal = flexDir === 'row' || flexDir === 'row-reverse';

                if (!isHorizontal) {{
                    let foundCurrent = false;
                    for (const sibling of parent.children) {{
                        if (sibling === currentElement) {{ foundCurrent = true; continue; }}
                        if (!foundCurrent) continue;
                        if (sibling.nodeType !== Node.ELEMENT_NODE) continue;
                        const tag = sibling.tagName;
                        if (tag === 'SCRIPT' || tag === 'STYLE') continue;
                        if (tag === 'INPUT' && sibling.type === 'hidden') continue;
                        const s = getComputedStyle(sibling);
                        if (s.display === 'none') continue;
                        const mt = parseFloat(s.marginTop) || 0;
                        const mb = parseFloat(s.marginBottom) || 0;
                        spaceUsedBelow += sibling.getBoundingClientRect().height + mt + mb;
                    }}
                }}

                currentElement = parent;
                parent = parent.parentElement;
            }}
            return spaceUsedBelow;
        }}

        function calculateAndSetViewportHeight() {{
            {container_resolution}
            const cardStack = document.getElementById('{ids.card_stack}');
            const cardStackInner = document.getElementById('{ids.card_stack_inner}');
            if (!container || !cardStack) return 400;

            // Compute sibling space by subtraction: everything in the
            // container except the card stack.  This avoids collapsing
            // the card stack to 0 which distorts flex layouts.
            const containerRect = container.getBoundingClientRect();
            const cardStackHeight = cardStack.getBoundingClientRect().height;
            const siblingSpace = Math.max(0, containerRect.height - cardStackHeight);

            const windowHeight = window.innerHeight;
            const containerTop = containerRect.top;
            const spaceBelow = calculateSpaceBelowContainer(container);

            const viewportHeight = Math.floor(Math.max(200,
                windowHeight - containerTop - siblingSpace - spaceBelow
            ));

            cardStack.style.height = viewportHeight + 'px';
            cardStack.style.maxHeight = viewportHeight + 'px';
            cardStack.style.minHeight = viewportHeight + 'px';
            if (cardStackInner) cardStackInner.style.height = viewportHeight + 'px';

            return viewportHeight;
        }}

        function _debounce(fn, delay) {{
            let tid;
            return function(...args) {{ clearTimeout(tid); tid = setTimeout(() => fn.apply(this, args), delay); }};
        }}

        const _debouncedResize = _debounce(function() {{
            calculateAndSetViewportHeight();
            if (ns.triggerAutoAdjust) ns.triggerAutoAdjust();
        }}, 100);

        // Remove old resize listener from previous IIFE (handles HTMX page
        // navigation that re-executes this script without a full page reload).
        if (window.{handler_key}) {{
            window.removeEventListener('resize', window.{handler_key});
        }}
        window.{handler_key} = _debouncedResize;
        window.addEventListener('resize', _debouncedResize);

        // Expose on namespace
        ns.recalculateHeight = calculateAndSetViewportHeight;
    """
