"""JavaScript generator for automatic visible card count adjustment."""

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

# %% auto #0
__all__ = []

# %% ../../nbs/js/auto_adjust.ipynb #aa000003
from typing import Optional

from ..core.config import CardStackConfig
from ..core.html_ids import CardStackHtmlIds
from ..core.models import CardStackUrls
from ..core.constants import DEFAULT_VISIBLE_COUNT

# %% ../../nbs/js/auto_adjust.ipynb #aa000005
def _generate_auto_adjust_js(
    ids: CardStackHtmlIds,  # HTML IDs for this instance
    config: CardStackConfig,  # Config for auto mode check
    urls: CardStackUrls,  # URL bundle (update_viewport)
    focus_position: Optional[int] = None,  # Focus slot offset (None=center, -1=bottom, 0=top)
) -> str:  # JS code fragment for auto visible count adjustment
    """Generate JS for automatic visible count adjustment based on overflow detection."""
    js_focus_pos = "null" if focus_position is None else str(focus_position)
    return f"""
        // === Auto Visible Count Adjustment ===
        let _autoAdjusting = false;
        let _autoAdjustTimer = null;
        const _AUTO_FOCUS_POS = {js_focus_pos};
        const _AUTO_STEP = (_AUTO_FOCUS_POS === null) ? 2 : 1;

        // --- Growth validation state ---
        let _autoGrowing = false;
        let _autoReverting = false;
        let _preGrowthItemIds = null;
        let _preGrowthCount = 0;

        function _getAutoCurrentCount() {{
            const cs = document.getElementById('{ids.card_stack}');
            return cs ? parseInt(cs.dataset.visibleCount || '{DEFAULT_VISIBLE_COUNT}') : {DEFAULT_VISIBLE_COUNT};
        }}

        function _getAutoTotalItems() {{
            const cs = document.getElementById('{ids.card_stack}');
            return cs ? parseInt(cs.dataset.totalItems || '0') : 0;
        }}

        function _getAutoSectionOverflow() {{
            // Returns max overflow (px) across relevant sections.
            // Before section uses justify-end, so content overflows upward (out the top).
            // After section uses justify-start, so content overflows downward (out the bottom).
            const before = document.getElementById('{ids.viewport_section_before}');
            const after = document.getElementById('{ids.viewport_section_after}');
            let maxOverflow = 0;

            const checkBefore = (_AUTO_FOCUS_POS === null || _AUTO_FOCUS_POS > 0 || _AUTO_FOCUS_POS < 0);
            const checkAfter = (_AUTO_FOCUS_POS === null || _AUTO_FOCUS_POS >= 0);

            // Before section: check if first child extends above container top
            if (checkBefore && before && before.children.length > 0) {{
                const sRect = before.getBoundingClientRect();
                const firstChild = before.children[0];
                const childRect = firstChild.getBoundingClientRect();
                const o = sRect.top - childRect.top;  // positive if child above container
                if (o > maxOverflow) maxOverflow = o;
            }}

            // After section: check if last child extends below container bottom
            if (checkAfter && after && after.children.length > 0) {{
                const sRect = after.getBoundingClientRect();
                const lastChild = after.children[after.children.length - 1];
                const childRect = lastChild.getBoundingClientRect();
                const o = childRect.bottom - sRect.bottom;  // positive if child below container
                if (o > maxOverflow) maxOverflow = o;
            }}

            return maxOverflow;
        }}

        function _getAutoAvgCardHeight() {{
            // Average height of rendered viewport-slot elements.
            const cs = document.getElementById('{ids.card_stack}');
            if (!cs) return 100;
            const slots = cs.querySelectorAll('.viewport-slot');
            if (slots.length === 0) return 100;
            let total = 0;
            for (const s of slots) total += s.getBoundingClientRect().height;
            return total / slots.length;
        }}

        function _getAutoGapPx() {{
            // Read computed gap from the before section (or after).
            const section = document.getElementById('{ids.viewport_section_before}')
                         || document.getElementById('{ids.viewport_section_after}');
            if (!section) return 16;
            return parseFloat(getComputedStyle(section).gap) || 16;
        }}

        // --- Growth validation helpers ---

        function _snapshotItemIds() {{
            const cs = document.getElementById('{ids.card_stack}');
            if (!cs) return new Set();
            const slots = cs.querySelectorAll('.viewport-slot');
            const idSet = new Set();
            for (const s of slots) {{
                if (s.id) idSet.add(s.id);
            }}
            return idSet;
        }}

        function _hideNewItems() {{
            if (!_preGrowthItemIds) return;
            const cs = document.getElementById('{ids.card_stack}');
            if (!cs) return;
            const slots = cs.querySelectorAll('.viewport-slot');
            for (const s of slots) {{
                if (s.id && !_preGrowthItemIds.has(s.id)) {{
                    s.style.opacity = '0';
                }}
            }}
        }}

        function _revealNewItems() {{
            const cs = document.getElementById('{ids.card_stack}');
            if (!cs) return;
            const slots = cs.querySelectorAll('.viewport-slot');
            for (const s of slots) {{
                if (s.style.opacity === '0') {{
                    s.style.removeProperty('opacity');
                }}
            }}
        }}

        function _validateGrowth() {{
            const overflow = _getAutoSectionOverflow();
            if (overflow > 2) {{
                // Growth caused overflow — revert to pre-growth count and stop
                _autoGrowing = false;
                _autoReverting = true;
                _preGrowthItemIds = null;
                _autoAdjusting = true;
                ns._autoUpdateCount(_preGrowthCount);
            }} else {{
                // Growth fits — reveal the new items
                _revealNewItems();
                _autoGrowing = false;
                _preGrowthItemIds = null;
                // Continue to check if there's still room for more
                requestAnimationFrame(function() {{
                    ns._runAutoAdjust();
                }});
            }}
        }}

        ns._cancelAutoGrowth = function() {{
            if (_autoGrowing) {{
                _revealNewItems();
                _autoGrowing = false;
                _preGrowthItemIds = null;
                _preGrowthCount = 0;
            }}
            _autoReverting = false;
        }};

        ns._runAutoAdjust = function() {{
            if (!_isAutoMode() || _autoAdjusting) return;

            // If we just reverted from a failed growth, stop the loop
            if (_autoReverting) {{
                _autoReverting = false;
                return;
            }}

            // If in growth validation cycle, validate instead of normal adjust
            if (_autoGrowing) {{
                _validateGrowth();
                return;
            }}

            const currentCount = _getAutoCurrentCount();
            const totalItems = _getAutoTotalItems();
            if (totalItems === 0) return;

            const overflow = _getAutoSectionOverflow();
            const avgHeight = _getAutoAvgCardHeight();
            const gapPx = _getAutoGapPx();

            if (overflow > 2) {{
                // Overflow exists — remove enough cards to eliminate it
                const toRemove = Math.ceil(overflow / (avgHeight + gapPx));
                const adjusted = (_AUTO_FOCUS_POS === null)
                    ? Math.max(_AUTO_STEP, Math.ceil(toRemove / 2) * 2)
                    : Math.max(_AUTO_STEP, toRemove);
                const newCount = Math.max(1, currentCount - adjusted);
                if (newCount !== currentCount) {{
                    _autoAdjusting = true;
                    ns._autoUpdateCount(newCount);
                }}
            }} else {{
                // No overflow — try to add more cards incrementally
                if (currentCount >= totalItems) return;

                const newCount = Math.min(totalItems, currentCount + _AUTO_STEP);
                if (newCount > currentCount) {{
                    // Snapshot current state before growth
                    _preGrowthCount = currentCount;
                    _preGrowthItemIds = _snapshotItemIds();
                    _autoGrowing = true;
                    _autoAdjusting = true;
                    ns._autoUpdateCount(newCount);
                }}
            }}
        }};

        ns.triggerAutoAdjust = function() {{
            // Debounced entry point for external triggers (resize, width, scale).
            if (!_isAutoMode()) return;
            clearTimeout(_autoAdjustTimer);
            _autoReverting = false;
            _autoAdjustTimer = setTimeout(function() {{
                ns._runAutoAdjust();
            }}, 200);
        }};
    """
