"""JavaScript generator for scroll wheel to navigation conversion."""

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

# %% auto #0
__all__ = ['SCROLL_THRESHOLD', 'NAVIGATION_COOLDOWN', 'TRACKPAD_COOLDOWN', 'generate_scroll_nav_js']

# %% ../../nbs/js/scroll.ipynb #d2852076
from typing import Tuple

from ..core.html_ids import VirtualCollectionHtmlIds
from ..core.button_ids import VirtualCollectionButtonIds

# %% ../../nbs/js/scroll.ipynb #71d5f63b
SCROLL_THRESHOLD = 1       # Minimum accumulated delta to trigger navigation (px)
NAVIGATION_COOLDOWN = 100  # Mouse wheel cooldown (ms)
TRACKPAD_COOLDOWN = 250    # Trackpad cooldown (ms) — higher to prevent rapid-fire

# %% ../../nbs/js/scroll.ipynb #5499e879
def generate_scroll_nav_js(
    ids: VirtualCollectionHtmlIds,       # HTML IDs for this collection
    button_ids: VirtualCollectionButtonIds,  # Button IDs for nav triggers
    disable_in_modes: Tuple[str, ...] = (),  # Mode names where scroll is suppressed
) -> str:  # JavaScript IIFE
    """Generate JS for scroll wheel to navigation conversion."""
    # Build optional mode check (safe fallback if keyboard nav not loaded)
    if disable_in_modes:
        modes_array = ', '.join(f"'{m}'" for m in disable_in_modes)
        mode_check = f"""
        function _isScrollDisabled() {{
            if (typeof window.kbNav !== 'undefined') {{
                const state = window.kbNav.getState();
                const disabledModes = [{modes_array}];
                return state && disabledModes.includes(state.currentMode);
            }}
            return false;
        }}
        """
        mode_guard = "if (_isScrollDisabled()) return;"
    else:
        mode_check = ""
        mode_guard = ""

    trackpad_detect_threshold = 50

    return f"""(function() {{
        // === Scroll Navigation ===
        const _scrollState = {{ accumulatedDelta: 0, lastNavTime: 0 }};
        const _SCROLL_THRESHOLD = {SCROLL_THRESHOLD};
        const _NAV_COOLDOWN = {NAVIGATION_COOLDOWN};
        const _TRACKPAD_COOLDOWN = {TRACKPAD_COOLDOWN};
        const _TRACKPAD_DETECT = {trackpad_detect_threshold};
        {mode_check}
        function _setupScrollNav() {{
            const el = document.getElementById('{ids.collection}');
            if (!el) return;

            // Abort previous listeners (handles re-setup after HTMX swaps)
            if (el._scrollNavAbort) el._scrollNavAbort.abort();
            const controller = new AbortController();
            el._scrollNavAbort = controller;

            el.addEventListener('wheel', function(evt) {{
                {mode_guard}
                evt.preventDefault();

                // Normalize deltaY based on deltaMode
                let deltaY = evt.deltaY;
                if (evt.deltaMode === 1) deltaY *= 32;      // DOM_DELTA_LINE
                else if (evt.deltaMode === 2) deltaY *= 800; // DOM_DELTA_PAGE

                // Pick cooldown: small deltas = trackpad
                const cooldown = Math.abs(deltaY) < _TRACKPAD_DETECT
                    ? _TRACKPAD_COOLDOWN : _NAV_COOLDOWN;

                const eventTime = evt.timeStamp;

                if (eventTime - _scrollState.lastNavTime > cooldown * 2) {{
                    _scrollState.accumulatedDelta = 0;
                }}
                _scrollState.accumulatedDelta += deltaY;

                if (Math.abs(_scrollState.accumulatedDelta) < _SCROLL_THRESHOLD) return;

                if (eventTime - _scrollState.lastNavTime >= cooldown) {{
                    const btnId = _scrollState.accumulatedDelta > 0
                        ? '{button_ids.nav_down}' : '{button_ids.nav_up}';
                    _scrollState.accumulatedDelta = 0;
                    _scrollState.lastNavTime = eventTime;
                    const btn = document.getElementById(btnId);
                    if (btn) btn.click();
                }} else if (eventTime === _scrollState.lastNavTime) {{
                    _scrollState.accumulatedDelta = 0;
                }}
            }}, {{ passive: false, signal: controller.signal }});
        }}

        // Setup on load and expose for re-setup after HTMX swaps
        _setupScrollNav();
        document.body.addEventListener('htmx:afterSettle', function(evt) {{
            _setupScrollNav();
        }});
    }})();"""
