/**
 * Elementor frontend handler for the Scroll Navigation Dots widget.
 *
 * Tracks page sections with an IntersectionObserver ( a zero-height root band at
 * the viewport centre marks the active section ) and smooth-scrolls to a target
 * on click, honouring the configured offset. Falls back to scroll-position math
 * when IntersectionObserver is unavailable. Dependency-free with editor-safe
 * teardown.
 *
 * @package captain-widgets-kit
 * @since   1.6.0
 */

(function ($) {
    'use strict';

    /**
     * Per-instance handler — called by Elementor for every widget instance.
     *
     * @param {jQuery} $scope - The widget wrapper element.
     */
    var CaptwikiScrollDotsHandler = function ($scope) {

        var root = $scope[0].querySelector('.captwiki-scrolldots');
        if (!root) {
            return;
        }

        // Re-run safe: tear down a previous controller on editor re-render.
        if (root._cwkDotsTeardown) {
            root._cwkDotsTeardown();
        }

        var dots = Array.prototype.slice.call(root.querySelectorAll('.captwiki-scrolldots__dot'));
        if (!dots.length) {
            return;
        }

        var smooth = root.getAttribute('data-smooth') === 'yes';
        var offset = parseInt(root.getAttribute('data-offset'), 10) || 0;

        var handlers = [];
        var observer = null;

        var on = function (el, evt, fn, opts) {
            el.addEventListener(evt, fn, opts || false);
            handlers.push(function () {
                el.removeEventListener(evt, fn, opts || false);
            });
        };

        // Resolve each dot to its target element ( skip the ones that aren't found ).
        var map = [];
        dots.forEach(function (dot) {
            var selector = dot.getAttribute('data-target');
            if (!selector) {
                return;
            }
            var section = null;
            try {
                section = document.querySelector(selector);
            } catch (e) {
                section = null;
            }
            if (section) {
                map.push({ dot: dot, section: section });
            }
        });

        /**
         * Mark a single dot active and clear the rest.
         *
         * @param {Element} activeDot - The dot to activate.
         */
        var setActive = function (activeDot) {
            map.forEach(function (pair) {
                var isActive = pair.dot === activeDot;
                pair.dot.classList.toggle('is-active', isActive);
                if (isActive) {
                    pair.dot.setAttribute('aria-current', 'true');
                } else {
                    pair.dot.removeAttribute('aria-current');
                }
            });
        };

        /* ── Click: smooth-scroll to target ────────────────── */
        dots.forEach(function (dot) {
            on(dot, 'click', function (e) {
                var selector = dot.getAttribute('data-target');
                var section = null;
                try {
                    section = selector ? document.querySelector(selector) : null;
                } catch (err) {
                    section = null;
                }
                if (!section) {
                    return;
                }
                e.preventDefault();
                var top = section.getBoundingClientRect().top + window.pageYOffset - offset;
                window.scrollTo({
                    top: top,
                    behavior: smooth ? 'smooth' : 'auto'
                });
            });
        });

        /* ── Active tracking ───────────────────────────────── */
        if (typeof window.IntersectionObserver !== 'undefined' && map.length) {
            observer = new IntersectionObserver(function (entries) {
                entries.forEach(function (entry) {
                    if (entry.isIntersecting) {
                        var match = map.filter(function (pair) {
                            return pair.section === entry.target;
                        })[0];
                        if (match) {
                            setActive(match.dot);
                        }
                    }
                });
            }, {
                // A thin band near the centre — the section crossing it is active.
                rootMargin: '-45% 0px -45% 0px',
                threshold: 0
            });

            map.forEach(function (pair) {
                observer.observe(pair.section);
            });
        } else {
            // Fallback: pick the section whose top is closest above the offset line.
            var onScroll = function () {
                var pos = window.pageYOffset + offset + 2;
                var current = null;
                map.forEach(function (pair) {
                    if (pair.section.offsetTop <= pos) {
                        current = pair.dot;
                    }
                });
                if (current) {
                    setActive(current);
                }
            };
            on(window, 'scroll', onScroll, { passive: true });
            onScroll();
        }

        /* ── Teardown ──────────────────────────────────────── */
        root._cwkDotsTeardown = function () {
            handlers.forEach(function (off) {
                off();
            });
            handlers = [];
            if (observer) {
                observer.disconnect();
                observer = null;
            }
            root._cwkDotsTeardown = null;
        };
    };

    /* ── Register with Elementor frontend ───────────────────── */
    $(window).on('elementor/frontend/init', function () {
        elementorFrontend.hooks.addAction(
            'frontend/element_ready/captwiki-scroll-navigation-dots.default',
            CaptwikiScrollDotsHandler
        );
    });

})(jQuery);
