jQuery(window).on("elementor/frontend/init", function () {

    var SvgAnimatorHandler = elementorModules.frontend.handlers.Base.extend({

        onInit: function () {
            this.runAnimation();
        },

        runAnimation: function () {
            var $wrapper = this.$element.find('.wpmozo_svg_animator_wrapper');

            if (!$wrapper.length) return;

            // ---- Easing Map ----
            function wpmozoMapCurve(curve) {
                curve = (curve || 'linear').toLowerCase();
                var map = {
                    'linear': 'linear',
                    'ease': 'ease',
                    'ease-in': 'ease-in',
                    'ease-out': 'ease-out',
                    'ease-in-out': 'ease-in-out',
                    'bounce': 'cubic-bezier(.34, 1.56, .64, 1)',
                    'back': 'cubic-bezier(.36, -0.55, .27, 1.55)',
                    'elastic': 'cubic-bezier(.5, -0.8, .25, 1.65)'
                };
                return map[curve] || 'linear';
            }

            // ---- Length Calculator ----
            function wpmozoGetElementLength(el) {
                switch (el.tagName.toLowerCase()) {
                    case 'circle':
                        return 2 * Math.PI * el.r.baseVal.value;
                    case 'rect':
                        return 2 * (el.width.baseVal.value + el.height.baseVal.value);
                    case 'ellipse':
                        return 2 * Math.PI * Math.sqrt(
                            (el.rx.baseVal.value ** 2 + el.ry.baseVal.value ** 2) / 2
                        );
                    case 'line':
                        return Math.hypot(
                            el.x2.baseVal.value - el.x1.baseVal.value,
                            el.y2.baseVal.value - el.y1.baseVal.value
                        );
                    case 'polygon':
                    case 'polyline':
                        var pts = el.points, len = 0;
                        for (var i = 0; i < pts.numberOfItems - 1; i++) {
                            let p1 = pts.getItem(i);
                            let p2 = pts.getItem(i + 1);
                            len += Math.hypot(p2.x - p1.x, p2.y - p1.y);
                        }
                        return len;
                    default:
                        return el.getTotalLength ? el.getTotalLength() : 0;
                }
            }

            // ---- Animate SVG ----
            function wpmozoAnimateSVG($wrap) {

                var animType = $wrap.data('svg_anim_type') || 'delayed';
                var duration = parseInt($wrap.data('svg_anim_duration')) || 1000;
                var curve = wpmozoMapCurve($wrap.data('svg_anim_curves'));

                var $svg = $wrap.find('svg');
                if (!$svg.length) return;

                var $elements = $svg.find('path, rect, circle, ellipse, polygon, polyline, line');

                var baseTime = Math.max(duration / 1000, 0.1);

                $elements.each(function (i, el) {
                    var len = wpmozoGetElementLength(el);
                    jQuery(el).css({
                        'stroke-dasharray': len,
                        'stroke-dashoffset': len,
                        'transition': 'none'
                    });
                });

                let totalDelay = 0;

                $elements.each(function (index, el) {

                    let $el = jQuery(el);
                    let delay = 0;

                    if (animType === 'sync') {
                        delay = 0;
                    } else if (animType === 'delayed') {
                        delay = index * (baseTime * 0.15);
                    } else if (animType === 'onebyone') {
                        delay = totalDelay;
                        totalDelay += (baseTime - 0.3);
                    }

                    setTimeout(function () {
                        $el.css({
                            'transition': 'stroke-dashoffset ' + baseTime + 's ' + curve,
                            'stroke-dashoffset': 0
                        });
                    }, delay * 1000);

                });
            }

            // ---- Viewport Detection ----
            function wpmozoIsInViewport(el) {
                let rect = el.getBoundingClientRect();
                return rect.top < window.innerHeight && rect.bottom > 0;
            }

            function wpmozoCheckAndAnimate() {
                if (wpmozoIsInViewport($wrapper[0]) && !$wrapper.hasClass('wpmozo-animated')) {
                    wpmozoAnimateSVG($wrapper);
                    $wrapper.addClass('wpmozo-animated');
                } else if ($wrapper.hasClass('wpmozo-animated')){
                    jQuery(window).off('scroll resize', wpmozoCheckAndAnimate);
                }
            }

            wpmozoCheckAndAnimate();

            jQuery(window).on('scroll resize', wpmozoCheckAndAnimate);

            // ---- Click Reanimate ----
            if ($wrapper.data('re_animate_on_click') === 'on') {
                $wrapper.on('click', 'svg', function () {
                    $wrapper.removeClass('wpmozo-animated');
                    wpmozoAnimateSVG($wrapper);
                    $wrapper.addClass('wpmozo-animated');
                });
            }
        }
    });

    elementorFrontend.elementsHandler.attachHandler("wpmozo_ae_svg_animator", SvgAnimatorHandler);
});
