( function( $ ) {

    var pxl_swiper_handler = function( $scope, $ ) {

        var breakpoints = elementorFrontend.config.breakpoints,
            carousel = $scope.find(".pxl-swiper-container");
        if(carousel.length == 0){
            return false;
        }

        /* Thumbs Slider */
        var galleryThumbs = new Swiper('.pxl-swiper-thumbs', {
            slidesPerView: 'auto',
            spaceBetween: 0,
            freeMode: false,
            allowTouchMove: true,
            centeredSlides: false,
            touchRatio: 0.2,
            slideToClickedSlide: true,
            loop: true,
            loopedSlides: 4,
            // initialSlide: 1
        });

        var numberOfSlides = carousel.find(".pxl-swiper-slide").length;

        /* Main Slider */
        var data = carousel.data(),
            settings = data.settings,
            carousel_settings = {
                direction: settings['slide_direction'],
                effect: settings['slide_mode'],
                wrapperClass : 'pxl-swiper-wrapper',
                slideClass: 'pxl-swiper-slide',
                slidesPerView: settings['slides_to_show'],
                slidesPerGroup: settings['slides_to_scroll'],
                slidesPerColumn: settings['slide_percolumn'],
                spaceBetween: 0,
                navigation: {
                    nextEl: $scope.find(".pxl-swiper-arrow-next"),
                    prevEl: $scope.find(".pxl-swiper-arrow-prev"),
                },
                pagination : {
                    el: $scope.find(".pxl-swiper-dots"),
                    clickable : true,
                    dynamicBullets: true,
                    modifierClass: 'pxl-swiper-pagination-',
                    bulletClass : 'pxl-swiper-pagination-bullet',
                    renderCustom: function (swiper, element, current, total) {
                        return current + ' of ' + total;
                    },
                    type: settings['pagination_type'],
                },
                speed: settings['speed'],
                watchSlidesProgress: true,
                watchSlidesVisibility: true,
                breakpoints: {
                    0 : {
                        slidesPerView: settings['slides_to_show_xs'],
                        slidesPerGroup: settings['slides_to_scroll'],
                    },
                    576 : {
                        slidesPerView: settings['slides_to_show_sm'],
                        slidesPerGroup: settings['slides_to_scroll'],
                    },
                    768 : {
                        slidesPerView: settings['slides_to_show_md'],
                        slidesPerGroup: settings['slides_to_scroll'],
                    },
                    992 : {
                        slidesPerView: settings['slides_to_show_lg'],
                        slidesPerGroup: settings['slides_to_scroll'],
                    },
                    1200 : {
                        slidesPerView: settings['slides_to_show'],
                        slidesPerGroup: settings['slides_to_scroll'],
                    },
                    1600 : {
                        slidesPerView: settings['slides_to_show_xxl'],
                        slidesPerGroup: settings['slides_to_scroll'],
                    }
                }
            };

            // center
            if(settings['center'] === 'true'){
                if(settings['loop'] === 'true'){
                    carousel_settings['initialSlide'] = Math.floor(numberOfSlides / 2);
                } else {
                    if(carousel_settings['slidesPerView'] > 1){
                        carousel_settings['initialSlide'] = Math.floor((numberOfSlides - carousel_settings['slidesPerView']) / 2);
                    } else {
                        carousel_settings['initialSlide'] = Math.ceil((numberOfSlides / 2) - 1);
                    }
                }
            }

            // effect
            if(settings['slide_mode'] === 'fade'){
                carousel_settings['fadeEffect'] = {
                    crossFade: true
                };
            }
            // parallax
            if(settings['parallax'] === 'true'){
                carousel_settings['parallax'] = true;
            }
            // loop
            if(settings['loop'] === 'true'){
                carousel_settings['loop'] = true;
            }
            // auto play
            if(settings['autoplay'] === 'true'){
                carousel_settings['autoplay'] = {
                    delay : settings['delay'],
                    disableOnInteraction : settings['pause_on_interaction']
                };
            } else {
                carousel_settings['autoplay'] = false;
            }
            // mouse wheel
            if(settings['mousewheel'] === 'true'){
                carousel_settings['mousewheel'] = true;
                carousel_settings['keyboard'] = {
                    enabled: true
                };
            }
            // vertical
            if(settings['slide_direction'] === 'vertical') {
                var swiper_slider = $scope.find('.pxl-swiper-sliders');
                var swiper_container = $scope.find('.pxl-swiper-container');
                var content_wrapper = $scope.find('.pxl-item--inner');
                $(window).on("resize", function() {
                    var bodyheight = content_wrapper.height();
                    swiper_slider.height(bodyheight);
                    swiper_container.height(bodyheight);
                }).resize();
            }

        carousel.each(function(index, element) {

            if($(this).closest('.pxl-swiper-sliders').find('.pxl-swiper-thumbs').length > 0){
                carousel_settings['thumbs'] = { swiper: galleryThumbs };
            }

            var swiper = new Swiper(carousel, carousel_settings);

            if(settings['autoplay'] === 'true' && settings['pause_on_hover'] === 'true'){
                $(this).on({
                    mouseenter: function mouseenter() {
                        this.swiper.autoplay.stop();
                    },
                    mouseleave: function mouseleave() {
                        this.swiper.autoplay.start();
                    }
                });
            }

            if (swiper && swiper.slides) {
                var slideCount = swiper.slides.length;
                if (slideCount <= 1) {
                    swiper.allowSlideNext = false;
                    swiper.allowSlidePrev = false;
                    swiper.allowTouchMove = false;
                }
            }

            $scope.find(".swiper-filter-wrap .filter-item").on("click", function(){
                var target = $(this).attr('data-filter-target');
                var parent = $(this).closest('.pxl-swiper-sliders');
                $(this).siblings().removeClass("active");
                $(this).addClass("active");

                if(target == "all"){
                    parent.find("[data-filter]").removeClass("non-swiper-slide").addClass("swiper-slide-filter");
                    swiper.destroy();
                    swiper = new Swiper(carousel, carousel_settings);
                } else {
                    parent.find(".swiper-slide-filter").not("[data-filter^='"+target+"'], [data-filter*=' "+target+"']").addClass("non-swiper-slide").removeClass("swiper-slide-filter");
                    parent.find("[data-filter^='"+target+"'], [data-filter*=' "+target+"']").removeClass("non-swiper-slide").addClass("swiper-slide-filter");
                    swiper.destroy();
                    swiper = new Swiper(carousel, carousel_settings);
                }
            });

            $('.swiper-filter-wrap').parents('.pxl-swiper-sliders').addClass('swiper-filter-active');

            // Custom Effects
            if($scope.find('.pxl-slider-carousel1').length > 0) {
                if ($(window).width() < 1200 && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
                    swiper.allowTouchMove = false;
                }
            }
            if($scope.find('.pxl-slider-carousel2').length > 0) {
                var postSlider = $scope.find('.pxl-slider-carousel2');
                postSlider.each(function () {
                    const sliderContainer = $(this);
                    var vertex = `
                        varying vec2 vUv;
                        void main() {
                            vUv = uv;
                            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
                        }
                    `;

                    var fragment = `
                        varying vec2 vUv;
                        uniform sampler2D currentImage;
                        uniform sampler2D nextImage;
                        uniform sampler2D disp;
                        uniform float dispFactor;
                        float intensity = 0.25;
                        void main() {
                            vec2 uv = vUv;
                            vec4 disp = texture2D(disp, uv);
                            vec2 distortedPosition = vec2(uv.x + dispFactor * (disp.r*intensity), uv.y);
                            vec2 distortedPosition2 = vec2(uv.x - (1.0 - dispFactor) * (disp.r*intensity), uv.y);
                            vec4 _currentImage = texture2D(currentImage, distortedPosition);
                            vec4 _nextImage = texture2D(nextImage, distortedPosition2);
                            vec4 finalTexture = mix(_currentImage, _nextImage, dispFactor);
                            gl_FragColor = finalTexture;
                        }
                    `;

                    let scene = new THREE.Scene();
                    let imgs = Array.from(sliderContainer.find('.item--image img'));
                    const sliderImages = []
                    var imgWidth = sliderContainer.find('.item--image img');
                    let renderWidth = imgWidth.width();
                    let renderHeight = imgWidth.height();

                    let imgCanvasSize = (renderWidth / renderHeight) + 1.194;

                    const camera = new THREE.PerspectiveCamera(
                        60,
                        imgCanvasSize,
                        1,
                        100
                    )
                    camera.position.z = 1

                    let renderer = new THREE.WebGLRenderer({
                        antialias: true,
                    });

                    renderer.setPixelRatio(window.devicePixelRatio);
                    renderer.setClearColor(0x23272A, 1.0);
                    renderer.setSize(renderWidth, renderHeight);

                    sliderContainer.append(renderer.domElement);

                    let textureLoader = new THREE.TextureLoader();
                    textureLoader.crossOrigin = "anonymous";

                    imgs.forEach(function (img) {
                        let image = textureLoader.load($(img).attr('src'));
                        image.magFilter = image.minFilter = THREE.LinearFilter;
                        image.anisotropy = renderer.capabilities.getMaxAnisotropy();
                        sliderImages.push(image);
                    });

                    let dispImgElement = sliderContainer.find('.pxl-image-webgl');
                    let dispImgSrc = dispImgElement.attr('src');

                    let dispImg = textureLoader.load(dispImgSrc);

                    dispImg.wrapS = dispImg.wrapT = THREE.RepeatWrapping;

                    let activeSlideIndex = 0;

                    if(settings['loop'] === 'true') {
                        activeSlideIndex = 1;
                    }

                    if(settings['center'] === 'true') {
                        if (numberOfSlides % 2 === 0) {
                            activeSlideIndex = settings['loop'] === 'true' ? 1 : 0;
                        } else {
                            activeSlideIndex = settings['loop'] === 'true' ? Math.floor(numberOfSlides / 2) + 1 : Math.floor(numberOfSlides / 2);
                        }
                    }

                    let mat = new THREE.ShaderMaterial({
                        uniforms: {
                            dispFactor: { type: "f", value: 0.0 },
                            currentImage: { type: "t", value: sliderImages[activeSlideIndex] },
                            nextImage: { type: "t", value: sliderImages[1] },
                            disp: { type: "t", value: dispImg },
                        },
                        vertexShader: vertex,
                        fragmentShader: fragment,
                        transparent: true,
                        opacity: 1.0
                    });

                    let geometry = new THREE.PlaneBufferGeometry(
                        2.4, 1.16
                    );

                    let object = new THREE.Mesh(geometry, mat);
                    object.position.set(0, 0, 0);
                    scene.add(object);

                    $(window).resize(function () {
                        renderWidth = imgWidth.width();
                        renderHeight = imgWidth.height();
                        renderer.setSize(renderWidth, renderHeight);
                        camera.aspect = (renderWidth / renderHeight) + 1.194;
                        camera.updateProjectionMatrix();
                    })

                    let animate = () => {
                        requestAnimationFrame(animate);
                        renderer.render(scene, camera);
                    };

                    animate();

                    let index = 0;

                    const animateDisplace = () => {
                        mat.uniforms.nextImage.value = sliderImages[index];
                        mat.uniforms.nextImage.needsUpdate = true;

                        TweenLite.to(mat.uniforms.dispFactor, 1, {
                            value: 1,
                            ease: 'Sine.easeInOut',
                            onComplete: () => {
                                mat.uniforms.currentImage.value = sliderImages[index];
                                mat.uniforms.currentImage.needsUpdate = true;
                                mat.uniforms.dispFactor.value = 0.0;
                            }
                        });
                    }

                    swiper.on('slideChange', function() {
                        index = this.activeIndex;
                        animateDisplace();
                    });

                    swiper.on('slideChangeTransitionStart', function() {
                        swiper.allowTouchMove = false;
                        postSlider.addClass('pxl-pointerev-none');
                    });
                    swiper.on('slideChangeTransitionEnd', function() {
                        setTimeout(function () {
                            swiper.allowTouchMove = true;
                            postSlider.removeClass('pxl-pointerev-none');
                        }, settings['speed']);
                    });

                });
            }

            if ($scope.find('.pxl-post-slider2').length > 0) {

                function setInnerTranslate(slide, progress) {
                    let innerOffset = swiper.height;
                    let innerTranslate = progress * innerOffset;
                    TweenMax.set(slide.querySelector(".pxl-item--inner"), {
                        y: innerTranslate,
                    });
                }

                function setSlideTransition(slide) {
                    slide.style.transition = settings['speed'] + "ms";
                    slide.querySelector(".pxl-item--inner").style.transition = settings['speed'] + "ms";
                }

                for (let i = 0; i < swiper.slides.length; i++) {
                    setInnerTranslate(swiper.slides[i], swiper.slides[i].progress);
                    setSlideTransition(swiper.slides[i]);
                }

                swiper.on('progress', function () {
                    let swiper = this;
                    for (let i = 0; i < swiper.slides.length; i++) {
                        setInnerTranslate(swiper.slides[i], swiper.slides[i].progress);
                    }
                });

                swiper.on('setTransition', function () {
                    let swiper = this;
                    for (let i = 0; i < swiper.slides.length; i++) {
                        setSlideTransition(swiper.slides[i]);
                    }
                });

                // $(document).ready(function() {
                //     swiper.allowTouchMove = false;
                // });

                // $(window).resize(function() {
                //     swiper.allowTouchMove = false;
                // });

            }


        });

    };

    // Make sure you run this code under Elementor.
    $( window ).on( 'elementor/frontend/init', function() {
        // Swipers
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_testimonial_carousel.default', pxl_swiper_handler );
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_post_carousel.default', pxl_swiper_handler );
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_instagram_carousel.default', pxl_swiper_handler );
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_team_carousel.default', pxl_swiper_handler );
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_pricing_carousel.default', pxl_swiper_handler );
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_slider_carousel.default', pxl_swiper_handler );
        elementorFrontend.hooks.addAction( 'frontend/element_ready/pxl_product_carousel.default', pxl_swiper_handler );
    } );
} )( jQuery );