/**
 * p11Carousel.js
 * Specialized for high-performance touch interactions and slide transitions.
 * Uses p11Js.Utility for swipe mathematics.
 */

export const CarouselFunctions = {
    _instances: new Map(),

    /**
     * Returns the current window width to determine the responsive slot count.
     */
    getWindowWidth: function () {
        return window.innerWidth;
    },

    /**
     * Initializes the carousel JS logic.
     * @param {HTMLElement} element - The main carousel container.
     * @param {string} instanceId - Unique ID from C#.
     * @param {object} dotNetRef - Reference to the Blazor component.
     */
    initialize: function (element, instanceId, dotNetRef) {
        if (!element) {
            console.error("[p11][Carousel] Initialization failed: Element is null.");
            return;
        }

        const state = {
            element: element,
            dotNetRef: dotNetRef,
            startX: 0,
            startY: 0,
            isSwiping: false,
            resizeHandler: resizeHandler
        };

        // 3. Den Event Listener registrieren
        window.addEventListener('resize', resizeHandler);

        // Debounce sorgt dafür, dass wir Blazor nicht mit Events überfluten
        let resizeTimeout;
        const resizeHandler = () => {
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(() => {
                dotNetRef.invokeMethodAsync('OnWindowResized', window.innerWidth)
                    .catch(err => console.error("[p11][Carousel] Resize callback failed:", err));
            }, 150); // 150ms warten, bis der User mit Skalieren fertig ist
        };

        window.addEventListener('resize', resizeHandler);

        // Event listener setup with passive:true for scroll performance
        // and passive:false for move (to allow preventDefault)
        const startHandler = (e) => this._handleTouchStart(e, state);
        const moveHandler = (e) => this._handleTouchMove(e, state);
        const endHandler = (e) => this._handleTouchEnd(e, state);

        element.addEventListener('touchstart', startHandler, { passive: true });
        element.addEventListener('touchmove', moveHandler, { passive: false });
        element.addEventListener('touchend', endHandler, { passive: true });

        // Store handlers for proper cleanup later
        state.cleanup = () => {
            element.removeEventListener('touchstart', startHandler);
            element.removeEventListener('touchmove', moveHandler);
            element.removeEventListener('touchend', endHandler);
        };

        this._instances.set(instanceId, state);
        window.p11Js.log("Carousel", `Instance ${instanceId} initialized.`);
    },

    _handleTouchStart: function (e, state) {
        const touch = e.touches ? e.touches[0] : null;
        if (!touch) return;

        state.startX = touch.clientX;
        state.startY = touch.clientY;
        state.isSwiping = true;
    },

    _handleTouchMove: function (e, state) {
        if (!state.isSwiping) return;

        // Use central utility for consistent math
        const metrics = window.p11Js.Utility.getSwipeMetrics(e, state.startX, state.startY);
        if (!metrics) return;

        // Prevent page scrolling only if swiping horizontally
        if (metrics.isHorizontal && e.cancelable) {
            e.preventDefault();
        }
    },

    _handleTouchEnd: function (e, state) {
        if (!state.isSwiping) return;
        state.isSwiping = false;

        // Calculate final metrics from changedTouches
        const metrics = window.p11Js.Utility.getSwipeMetrics(e, state.startX, state.startY);
        if (!metrics) return;

        const threshold = 50; // Minimum pixels to trigger slide

        if (metrics.isHorizontal && metrics.absX > threshold) {
            if (metrics.diffX > 0) {
                state.dotNetRef.invokeMethodAsync('Previous')
                    .catch(err => console.error("[p11][Carousel] Callback 'Previous' failed:", err));
            } else {
                state.dotNetRef.invokeMethodAsync('Next')
                    .catch(err => console.error("[p11][Carousel] Callback 'Next' failed:", err));
            }
        }
    },

    rotateSelection: function (containerElement, direction, itemsBefore, itemsAfter) {
        const slots = containerElement.querySelectorAll('.p11-selecting-slot');

        slots.forEach(slot => {
            const currentClass = Array.from(slot.classList).find(c => c.startsWith('p11-slot-pos-'));
            const currentIndex = parseInt(currentClass.split('pos-')[1]);

            let nextIndex;
            let isTeleport = false;

            if (direction === 'next') {
                nextIndex = currentIndex + 1;
                if (nextIndex > itemsAfter) {
                    nextIndex = -itemsBefore;
                    isTeleport = true; // Bild springt von rechts nach ganz links
                }
            } else {
                nextIndex = currentIndex - 1;
                if (nextIndex < -itemsBefore) {
                    nextIndex = itemsAfter;
                    isTeleport = true; // Bild springt von links nach ganz rechts
                }
            }

            if (isTeleport) {
                // 1. Animation sofort ausschalten
                slot.classList.add('p11-no-transition');

                // 2. Klasse tauschen (passiert sofort ohne Gleiten)
                slot.classList.remove(currentClass);
                slot.classList.add(`p11-slot-pos-${nextIndex}`);

                // 3. Animation nach einem winzigen Moment wieder erlauben
                // (RequestAnimationFrame stellt sicher, dass der Browser den Sprung erst ausführt)
                requestAnimationFrame(() => {
                    setTimeout(() => {
                        slot.classList.remove('p11-no-transition');
                    }, 10);
                });
            } else {
                // Normaler Slide-Vorgang
                slot.classList.remove(currentClass);
                slot.classList.add(`p11-slot-pos-${nextIndex}`);
            }
        });

        return new Promise(resolve => {
            setTimeout(() => resolve(), 600);
        });
    },

    /**
     * Removes the instance and its event listeners.
     */
    dispose: function (instanceId) {
        const state = this._instances.get(instanceId);
        if (state) {
            if (state.cleanup) state.cleanup();

            // Kleine Sicherheit: Nur entfernen, wenn der Handler auch da ist
            if (state.resizeHandler) {
                window.removeEventListener('resize', state.resizeHandler);
            }

            this._instances.delete(instanceId);
            window.p11Js.log("Carousel", `Instance ${instanceId} disposed.`);
        }
    }
};