jQuery(document).ready(function ($) {
    /**
     * GFEA Frontend Handler
     */
    var CRTGSFrontend = {
        init: function () {
            elementorFrontend.hooks.addAction('frontend/element_ready/widget', CRTGSFrontend.initGSAP);
            elementorFrontend.hooks.addAction('frontend/element_ready/section', CRTGSFrontend.initGSAP);
            elementorFrontend.hooks.addAction('frontend/element_ready/column', CRTGSFrontend.initGSAP);
            elementorFrontend.hooks.addAction('frontend/element_ready/container', CRTGSFrontend.initGSAP);
            CRTGSFrontend.initCursor();
            CRTGSFrontend.initHoverMarquee();
        },

        initCursor: function () {
            if ($('.crt-magic-cursor').length === 0) {
                var css = '<style>' +
                    '.crt-magic-cursor { position: fixed; top: 0; left: 0; pointer-events: none; z-index: 999999; ' +
                    'display: flex; align-items: center; justify-content: center; white-space: nowrap; ' +
                    'border-radius: 50%; opacity: 0; width: 0; height: 0; overflow: hidden; ' +
                    'transition: width 0.3s, height 0.3s, background-color 0.3s, opacity 0.3s; } ' +
                    '.crt-magic-cursor.is-hover-active { opacity: 1; ' +
                    'width: var(--cursor-size, 80px); height: var(--cursor-size, 80px); ' +
                    'background-color: var(--cursor-bg-color, #000); ' +
                    'color: var(--cursor-color, #fff); overflow: visible; } ' +
                    '.crt-magic-cursor.is-text-only { background-color: transparent !important; border-radius: 0 !important; width: auto !important; height: auto !important; padding: 0 10px; } ' +
                    '.crt-magic-cursor.is-text-only .crt-cursor-text { font-size: var(--cursor-size, 16px); line-height: 1; } ' +
                    '</style>';
                $('head').append(css);
                $('body').append('<div class="crt-magic-cursor"><span class="crt-cursor-text"></span></div>');

                var $cursor = $('.crt-magic-cursor');
                gsap.set($cursor, { xPercent: -50, yPercent: -50 });

                $(window).on('mousemove', function (e) {
                    gsap.to($cursor, { x: e.clientX, y: e.clientY, duration: 0.15, ease: "power2.out" });
                });

                $(document).on('mouseenter', '[data-cursor]:not([data-cursor-links="true"]), [data-cursor-links="true"] a', function () {
                    var $this = $(this).closest('[data-cursor]');
                    if ($this.length === 0) $this = $(this);

                    var text = $this.attr('data-cursor');
                    var id = $this.data('id');

                    // Copy computed css variables from wrapper to cursor
                    var size = $this.css('--cursor-size');
                    var bg = $this.css('--cursor-bg-color');
                    var color = $this.css('--cursor-color');
                    if (size) $cursor[0].style.setProperty('--cursor-size', size);
                    if (bg) $cursor[0].style.setProperty('--cursor-bg-color', bg);
                    if (color) $cursor[0].style.setProperty('--cursor-color', color);

                    if (id) { $cursor.attr('data-hover-id', id); }
                    if (text) { $cursor.find('.crt-cursor-text').text(text); }

                    if ($this.attr('data-cursor-text-only') === 'true') {
                        $cursor.addClass('is-text-only');
                    }

                    $cursor.addClass('is-hover-active');
                });

                $(document).on('mouseleave', '[data-cursor]:not([data-cursor-links="true"]), [data-cursor-links="true"] a', function () {
                    var $cursor = $('.crt-magic-cursor');
                    $cursor.removeClass('is-hover-active is-text-only');
                    $cursor.find('.crt-cursor-text').text('');
                    $cursor.removeAttr('data-hover-id');
                    $cursor[0].style.removeProperty('--cursor-size');
                    $cursor[0].style.removeProperty('--cursor-bg-color');
                    $cursor[0].style.removeProperty('--cursor-color');
                });

                // Magnetic Element Follow Effect
                $(document).on('mousemove', '[data-magnetic]', function (e) {
                    var $this = $(this);
                    var strength = parseFloat($this.attr('data-magnetic')) || 0.5;
                    var bounds = this.getBoundingClientRect();

                    // Core coordinates
                    var relX = e.clientX - bounds.left;
                    var relY = e.clientY - bounds.top;

                    // Normalize -1 to 1 based on center proximity
                    var x = (relX / bounds.width - 0.5) * 2;
                    var y = (relY / bounds.height - 0.5) * 2;

                    // Max distance scaled by strength (e.g. 50px core radius)
                    gsap.to(this, {
                        x: x * (50 * strength),
                        y: y * (50 * strength),
                        duration: 0.4,
                        ease: 'power2.out'
                    });
                });

                $(document).on('mouseleave', '[data-magnetic]', function () {
                    // Swift but bouncy anchor snap
                    gsap.to(this, {
                        x: 0,
                        y: 0,
                        duration: 0.7,
                        ease: 'elastic.out(1, 0.3)'
                    });
                });
            }
        },

        initHoverMarquee: function() {
            var $marquees = $('.crt-smh-container');
            if ($marquees.length === 0) return;

            // Global Tracker Setup
            if ($('.crt-smh-hover-img').length === 0) {
                $('body').append('<img src="" class="crt-smh-hover-img" />');
                
                var trackerImg = $('.crt-smh-hover-img')[0];
                gsap.set(trackerImg, { xPercent: -50, yPercent: -50, opacity: 0, scale: 0.6 });

                // Map mouse natively
                $(window).on('mousemove', function(e) {
                    if($(trackerImg).hasClass('is-active')) {
                        gsap.to(trackerImg, { x: e.clientX, y: e.clientY, duration: 0.15, ease: "power2.out", overwrite: "auto" });
                    } else {
                        gsap.set(trackerImg, { x: e.clientX, y: e.clientY });
                    }
                });

                $(document).on('mouseenter', '.crt-smh-item', function(e) {
                    var imgUrl = $(this).attr('data-hover-img');
                    var $container = $(this).closest('.crt-smh-container');
                    
                    if(imgUrl) {
                        var configuredHeight = $container.css('--hover-img-height');
                        if(configuredHeight) {
                            trackerImg.style.setProperty('height', configuredHeight);
                        }

                        var configuredRadius = $container.css('--hover-img-border-radius');
                        if(configuredRadius) {
                            trackerImg.style.setProperty('border-radius', configuredRadius);
                        }
                        
                        $(trackerImg).attr('src', imgUrl).addClass('is-active');
                        gsap.to(trackerImg, { opacity: 1, scale: 1, duration: 0.3, ease: 'power2.out' });
                    }
                });

                $(document).on('mouseleave', '.crt-smh-item', function(e) {
                    $(trackerImg).removeClass('is-active');
                    gsap.to(trackerImg, { opacity: 0, scale: 0.6, duration: 0.3, ease: 'power2.out' });
                });
            }

            // Marquee Scroll Behaviors
            $marquees.each(function() {
                var $container = $(this);
                var $track = $container.find('.crt-smh-track');
                var speed = parseFloat($container.data('speed')) || 2;
                
                // For a seamless endless effect powered purely by scroll (using gsap scrub)
                // We shift the track horizontally up to -50% of its massive width using scroll ratio
                gsap.to($track, {
                    x: function() { return -( $track.width() / 2 ); },
                    ease: "none",
                    scrollTrigger: {
                        trigger: $container[0],
                        start: "top bottom",
                        end: "bottom top",
                        scrub: speed, 
                    }
                });
            });
        },

        splitText: function ($element, mode) {
            // Target common text wrappers inside the element
            var $targetNodes = $element.find('h1, h2, h3, h4, h5, h6, p, span, div').filter(function () {
                // Filter elements that have direct text content and no children (leaf nodes mainly)
                return $(this).children().length === 0 && $(this).text().trim().length > 0;
            });

            // If no specific text children found, try the element itself
            if ($targetNodes.length === 0 && $element.text().trim().length > 0) {
                $targetNodes = $element;
            }

            $targetNodes.each(function () {
                var $node = $(this);
                var text = $node.text();
                var chars = text.split('');
                var words = text.split(' ');
                var html = '';

                if (mode === 'chars') {
                    $.each(chars, function (i, char) {
                        if (char === ' ') {
                            html += '&nbsp;';
                        } else {
                            html += '<span style="display:inline-block; opacity: 1;">' + char + '</span>';
                        }
                    });
                } else if (mode === 'words') {
                    $.each(words, function (i, word) {
                        html += '<span style="display:inline-block; opacity: 1;">' + word + '</span> ';
                    });
                }

                $node.html(html);
            });

            return $element.find('span'); // Return the created spans
        },

        initGSAP: function ($scope) {
            var $target = $scope;
            var settings = $target.data('gfea-settings');

            if (!settings) {
                return;
            }

            // GSAP Animation Logic
            var animationType = settings.type;
            var duration = parseFloat(settings.duration) || 1;
            var delay = parseFloat(settings.delay) || 0;
            var ease = settings.ease || 'power2.out';
            var $animTarget = $target[0];

            var animProps = {
                duration: duration,
                delay: delay,
                ease: ease
            };

            // Text Animation Handling
            if (animationType.indexOf('text-') === 0) {
                var stagger = 0.05;
                var mode = 'chars';
                if (animationType.indexOf('words') !== -1 || animationType.indexOf('lines') !== -1) {
                    mode = 'words'; // Fallback mapping for lines without premium plugin
                    stagger = 0.1;
                }

                var $spans = CRTGSFrontend.splitText($target, mode);
                if ($spans.length > 0) {
                    $animTarget = $spans;
                    animProps.stagger = stagger;
                }
            }

            // Define Animations
            switch (animationType) {
                // Standard Animations
                case 'fadeIn':
                    animProps.opacity = 0;
                    break;
                case 'fadeInUp':
                    animProps.y = 50;
                    animProps.opacity = 0;
                    break;
                case 'fadeInDown':
                    animProps.y = -50;
                    animProps.opacity = 0;
                    break;
                case 'fadeInLeft':
                    animProps.x = -50;
                    animProps.opacity = 0;
                    break;
                case 'fadeInRight':
                    animProps.x = 50;
                    animProps.opacity = 0;
                    break;
                case 'zoomIn':
                    animProps.scale = 0.5;
                    animProps.opacity = 0;
                    break;
                case 'zoomOut':
                    animProps.scale = 1.5;
                    animProps.opacity = 0;
                    break;
                case 'rotateIn':
                    animProps.rotation = -180;
                    animProps.opacity = 0;
                    break;
                case 'fromLeft':
                    animProps.x = '-100%';
                    animProps.opacity = 0;
                    break;
                case 'fromRight':
                    animProps.x = '100%';
                    animProps.opacity = 0;
                    break;
                case 'expandWidthLeft':
                    var widthInsetLeft = settings.width_from !== undefined && settings.width_from !== '' ? (100 - parseFloat(settings.width_from)) : 100;
                    animProps.clipPath = 'inset(0% ' + widthInsetLeft + '% 0% 0%)';
                    animProps.opacity = 0;
                    break;
                case 'expandWidthRight':
                    var widthInsetRight = settings.width_from !== undefined && settings.width_from !== '' ? (100 - parseFloat(settings.width_from)) : 100;
                    animProps.clipPath = 'inset(0% 0% 0% ' + widthInsetRight + '%)';
                    animProps.opacity = 0;
                    break;
                case 'expandHeightTop':
                    var heightInsetTop = settings.height_from !== undefined && settings.height_from !== '' ? (100 - parseFloat(settings.height_from)) : 100;
                    animProps.clipPath = 'inset(0% 0% ' + heightInsetTop + '% 0%)';
                    animProps.opacity = 0;
                    break;
                case 'expandHeightBottom':
                    var heightInsetBottom = settings.height_from !== undefined && settings.height_from !== '' ? (100 - parseFloat(settings.height_from)) : 100;
                    animProps.clipPath = 'inset(' + heightInsetBottom + '% 0% 0% 0%)';
                    animProps.opacity = 0;
                    break;
                case 'zoomInUp':
                    animProps.scale = 0.5;
                    animProps.y = 50;
                    animProps.opacity = 0;
                    break;
                case 'zoomInDown':
                    animProps.scale = 0.5;
                    animProps.y = -50;
                    animProps.opacity = 0;
                    break;
                case 'zoomInLeft':
                    animProps.scale = 0.5;
                    animProps.x = -50;
                    animProps.opacity = 0;
                    break;
                case 'zoomInRight':
                    animProps.scale = 0.5;
                    animProps.x = 50;
                    animProps.opacity = 0;
                    break;
                case 'rotateInUpLeft':
                    animProps.rotation = 45;
                    animProps.transformOrigin = "left bottom";
                    animProps.opacity = 0;
                    break;
                case 'rotateInUpRight':
                    animProps.rotation = -45;
                    animProps.transformOrigin = "right bottom";
                    animProps.opacity = 0;
                    break;
                case 'flipInX':
                    animProps.rotationX = 90;
                    animProps.opacity = 0;
                    break;
                case 'flipInY':
                    animProps.rotationY = 90;
                    animProps.opacity = 0;
                    break;
                case 'bounceIn':
                    animProps.scale = 0.3;
                    animProps.opacity = 0;
                    animProps.ease = "bounce.out";
                    break;
                case 'bounceInUp':
                    animProps.y = 100;
                    animProps.opacity = 0;
                    animProps.ease = "bounce.out";
                    break;
                case 'bounceInDown':
                    animProps.y = -100;
                    animProps.opacity = 0;
                    animProps.ease = "bounce.out";
                    break;
                case 'bounceInLeft':
                    animProps.x = -100;
                    animProps.opacity = 0;
                    animProps.ease = "bounce.out";
                    break;
                case 'bounceInRight':
                    animProps.x = 100;
                    animProps.opacity = 0;
                    animProps.ease = "bounce.out";
                    break;
                case 'slideInUp':
                    animProps.y = 100;
                    animProps.opacity = 0;
                    break;
                case 'slideInDown':
                    animProps.y = -100;
                    animProps.opacity = 0;
                    break;
                case 'slideInLeft':
                    animProps.x = -100;
                    animProps.opacity = 0;
                    break;
                case 'slideInRight':
                    animProps.x = 100;
                    animProps.opacity = 0;
                    break;

                // Text Animations
                case 'text-chars-fadeInUp':
                    animProps.y = 30;
                    animProps.opacity = 0;
                    break;
                case 'text-chars-typewriter':
                    animProps.opacity = 0;
                    animProps.duration = 0.01; // Almost instant per char
                    animProps.stagger = duration / $animTarget.length; // Spread duration
                    break;
                case 'text-chars-reveal':
                    animProps.opacity = 0;
                    animProps.y = 20;
                    animProps.rotationX = -90;
                    animProps.transformOrigin = "0% 50% -50";
                    break;
                case 'text-words-fadeIn':
                    animProps.y = 20;
                    animProps.opacity = 0;
                    break;
                case 'text-words-fadeInUp':
                case 'text-lines-fadeInUp':
                    animProps.y = 40;
                    animProps.opacity = 0;
                    break;
                case 'text-chars-opacity-scroll':
                case 'text-words-opacity-scroll':
                    if (!settings.scrollTrigger) settings.scrollTrigger = {};
                    settings.scrollTrigger.enable = 'yes';
                    settings.scrollTrigger.scrub = 'yes';
                    break;

                default:
                    animProps.opacity = 0;
            }

            // ScrollTrigger
            if (settings.scrollTrigger && settings.scrollTrigger.enable === 'yes') {
                animProps.scrollTrigger = {
                    trigger: $target[0],
                    start: settings.scrollTrigger.start || 'top 80%',
                    end: settings.scrollTrigger.end || 'bottom 20%',
                    scrub: settings.scrollTrigger.scrub === 'yes' ? true : false,
                    markers: settings.scrollTrigger.markers === 'yes' ? true : false,
                };
            }

            if (settings.opacity !== undefined && settings.opacity !== '') {
                animProps.opacity = parseFloat(settings.opacity);
            }

            var toStyle = { opacity: 1 };
            if (animationType === 'expandWidthLeft' || animationType === 'expandWidthRight') {
                toStyle.width = '100%';
                toStyle.clipPath = 'inset(0% 0% 0% 0%)';
            } else if (animationType === 'expandHeightTop' || animationType === 'expandHeightBottom') {
                toStyle.height = '100%';
                toStyle.clipPath = 'inset(0% 0% 0% 0%)';
            }

            gsap.set($target[0], toStyle);
            if ($animTarget !== $target[0]) {
                // E.g. for text mode spans
                gsap.set($animTarget, toStyle);
            }

            // Apply Animation
            gsap.from($animTarget, animProps);
        }
    };

    $(window).on('elementor/frontend/init', CRTGSFrontend.init);
});
