/**
 * Audace — smooth snap scrolling via the `scroll-snap` library.
 *
 * Uses the esm.sh CDN to load it as a native ES module (no bundler).
 * Replaces the former CSS `scroll-snap-type` rules; the library takes
 * over and programmatically animates scrollTop after the user stops.
 *
 * Stride = one viewport minus the admin bar + site header, so each
 * snap point lands with the slide's top at the sticky line.
 */
import createScrollSnap from '../vendor/scroll-snap.js';

const MIN_WIDTH = 782;

// Duration (ms) of the menu → slide scroll animation on desktop.
// Increase for a slower, more visible scroll; decrease for a snappier jump.
const MENU_SCROLL_MS = 2000;

function topOffset() {
    const adminBar = document.getElementById('wpadminbar');
    const header   = document.querySelector(
        '.audace-site-header, .wp-block-template-part.site-header, header.wp-block-template-part, #masthead'
    );
    const adminH  = adminBar ? adminBar.getBoundingClientRect().height : 0;
    const headerH = header   ? header.getBoundingClientRect().height   : 0;
    return adminH + headerH;
}

function slideHeight() {
    return Math.max(1, window.innerHeight - topOffset());
}

let controller = null;

function activate() {
    if (controller) { try { controller.unbind(); } catch (e) {} controller = null; }
    if (window.innerWidth < MIN_WIDTH) return;

    const scroller = document.scrollingElement || document.documentElement;
    if (!scroller) return;

    const api = createScrollSnap(
        scroller,
        {
            snapDestinationX: '0px',
            snapDestinationY: slideHeight() + 'px',
            timeout:  100,
            duration: 400,
            threshold: 0.2,
            snapStop: false,
            enableKeyboard: true,
        }
    );
    api.bind();
    controller = api; // { bind, unbind, snap }
}

if (document.readyState === 'complete') {
    activate();
} else {
    window.addEventListener('load', activate, { once: true });
}

/* Public API.
 *
 * snapTo(yTarget): step the library's internal `snap(direction)` one
 * stride at a time until the current stride matches the stride that
 * contains `yTarget`. Works WITH the library instead of against it, so
 * the subsequent user scroll isn't yanked back to the previous snap
 * point. Only usable on desktop (library isn't bound on mobile).
 */
window.audaceScrollSnap = {
    isActive() { return !!controller; },
    /* Jump to the slide that contains `targetEl`. With sticky slides, scroll
     * position inside a stride tells you nothing about which slide is
     * visually on top, so `scrollY/stride` is unreliable for going "up".
     * Use the slide's actual DOM index among all .is-style-slide elements
     * and set scrollTop = index * stride directly. Instant, no animation. */
    snapToElement(targetEl) {
        if (!controller) return false;
        const slides = Array.prototype.slice.call(
            document.querySelectorAll('.is-style-slide')
        );
        let idx = -1;
        for (let i = 0; i < slides.length; i++) {
            if (slides[i] === targetEl || slides[i].contains(targetEl)) {
                idx = i;
                break;
            }
        }
        if (idx < 0) return false;

        const scroller = document.scrollingElement || document.documentElement;
        const stride   = slideHeight();
        const from     = scroller.scrollTop;
        const to       = idx * stride;
        if (Math.abs(to - from) < 1) return true;

        /* Custom rAF-driven easing. Continuous scrollTop writes keep the
         * library from settling mid-way (so no snap-back), and the final
         * value is a stride multiple so there's nothing to snap to. */
        const duration = MENU_SCROLL_MS;
        const t0 = performance.now();
        const ease = (t) => 1 - Math.pow(1 - t, 3); // easeOutCubic
        function step(now) {
            const k = Math.min(1, (now - t0) / duration);
            scroller.scrollTop = from + (to - from) * ease(k);
            if (k < 1) requestAnimationFrame(step);
            else scroller.scrollTop = to;
        }
        requestAnimationFrame(step);
        return true;
    },
};

/* Rebind ONLY when the viewport crosses the desktop/mobile threshold.
 * A short delay lets the library's in-flight animation frame settle
 * before we bind a fresh instance. */
let lastIsDesktop = window.innerWidth >= MIN_WIDTH;
window.addEventListener('resize', () => {
    const isDesktop = window.innerWidth >= MIN_WIDTH;
    if (isDesktop === lastIsDesktop) return;
    lastIsDesktop = isDesktop;
    setTimeout(() => {
        try { activate(); }
        catch (e) { console.warn('[audace] scroll-snap activate failed:', e); }
    }, 50);
});
