(function ($) {
	$( window ).on( 'elementor/frontend/init', () => {
		class TestimonialsWidget extends elementorModules.frontend.handlers.Base {
			getDefaultSettings() {
				return {
					selectors: {
						testimonials: '.pp-testimonials',
						testimonialsWrap: '.pp-testimonials-wrap',
						swiperSlide: '.pp-testimonial-slide',
					},
					slidesPerView: {
						widescreen: 3,
						desktop: 3,
						laptop: 3,
						tablet_extra: 3,
						tablet: 2,
						mobile_extra: 2,
						mobile: 1
					}
				};
			}

			getDefaultElements() {
				const selectors = this.getSettings( 'selectors' );
				return {
					$testimonials: this.$element.find( selectors.testimonials ),
					$testimonialsWrap: this.$element.find( selectors.testimonialsWrap ),
					$swiperSlide: this.$element.find( selectors.swiperSlide ),
				};
			}

			getSlidesCount() {
				return this.elements.$swiperSlide.length;
			}

			getDeviceSlidesPerView(device) {
				const slidesPerViewKey = 'slides_per_view' + ('desktop' === device ? '' : '_' + device);
				return Math.min(this.getSlidesCount(), +this.getSliderSettings(slidesPerViewKey) || this.getSettings('slidesPerView')[device]);
			}

			getDeviceSlidesToScroll(device) {
				const slidesToScrollKey = 'slides_to_scroll' + ('desktop' === device ? '' : '_' + device);
				return Math.min(this.getSlidesCount(), +this.getSliderSettings(slidesToScrollKey) || 1);
			}

			getCenterPadding(device) {
				return elementorFrontend.utils.controls.getResponsiveControlValue(this.getSliderSettings(), 'center_padding', 'size', device) || 0;
			}

			getSpaceBetween(device) {
				const key = 'space_between' + ('desktop' === device ? '' : '_' + device);
				const val = this.getSliderSettings(key);
				return ( undefined === val || '' === val ) ? 0 : parseInt( val, 10 ) || 0;
			}

			getSliderSettings(prop) {
				const sliderSettings = ( undefined !== this.elements.$testimonialsWrap.data('slider-settings') ) ? this.elements.$testimonialsWrap.data('slider-settings') : '';

				if ( 'undefined' !== typeof prop && 'undefined' !== sliderSettings[prop] ) {
					return sliderSettings[prop];
				}

				return sliderSettings;
			}

			getSwiperOptions() {
				const sliderSettings = this.getSliderSettings();
				const useFade        = !!sliderSettings.fade;

				const swiperOptions = {
					slidesPerView:              useFade ? 1 : this.getDeviceSlidesPerView('desktop'),
					slidesPerGroup:             useFade ? 1 : this.getDeviceSlidesToScroll('desktop'),
					spaceBetween:               this.getSpaceBetween('desktop'),
					speed:                      sliderSettings.speed,
					loop:                       !!sliderSettings.loop,
					effect:                     useFade ? 'fade' : 'slide',
					direction:                  sliderSettings.vertical ? 'vertical' : 'horizontal',
					grabCursor:                 true,
					watchSlidesProgress:        true,
					handleElementorBreakpoints: true,
				};

				if ( useFade ) {
					swiperOptions.fadeEffect = { crossFade: true };
				}

				if ( sliderSettings.center_mode ) {
					swiperOptions.centeredSlides = true;
					const padding = this.getCenterPadding('desktop');
					if ( padding ) {
						swiperOptions.slidesOffsetBefore = padding;
						swiperOptions.slidesOffsetAfter  = padding;
					}
				}

				if ( sliderSettings.arrows ) {
					swiperOptions.navigation = {
						prevEl: '.pp-arrow-prev-' + this.getID(),
						nextEl: '.pp-arrow-next-' + this.getID(),
					};
				}

				if ( sliderSettings.dots ) {
					swiperOptions.pagination = {
						el: '.pp-testimonials-pagination-' + this.getID(),
						type: 'bullets',
						clickable: true,
					};
				}

				if ( ! useFade ) {
					const breakpointsSettings = {},
						breakpoints = elementorFrontend.config.responsive.activeBreakpoints;

					Object.keys(breakpoints).forEach((breakpointName) => {
						const bpValue = breakpoints[breakpointName].value;
						breakpointsSettings[bpValue] = {
							slidesPerView: this.getDeviceSlidesPerView(breakpointName),
							slidesPerGroup: this.getDeviceSlidesToScroll(breakpointName),
							spaceBetween: this.getSpaceBetween(breakpointName),
						};

						if ( sliderSettings.center_mode ) {
							const bpPadding = this.getCenterPadding(breakpointName);
							if ( bpPadding ) {
								breakpointsSettings[bpValue].slidesOffsetBefore = bpPadding;
								breakpointsSettings[bpValue].slidesOffsetAfter  = bpPadding;
							}
						}
					});

					swiperOptions.breakpoints = breakpointsSettings;
				}

				if ( ! this.isEdit && sliderSettings.autoplay ) {
					swiperOptions.autoplay = {
						delay: sliderSettings.autoplay_speed || 3000,
						disableOnInteraction: false,
					};
				}

				return swiperOptions;
			}

			bindEvents() {
				const layout          = this.elements.$testimonials.data( 'layout' ),
					elementSettings   = this.getElementSettings();

				if ( 'carousel' === layout || 'slideshow' === layout ) {
					this.initSlider().then( () => {
						if ( 'slideshow' === layout && 'yes' === elementSettings.thumbnail_nav ) {
							this.thumbsNav();
						}

						this.applyVerticalHeight();

						this.ppWidgetUpdate();

						this.widgetResize();
					} );
				}

				if ( 'masonry' === layout ) {
					this.initMasonryLayout();
				}
			}

			initMasonryLayout() {
				const self = this;

				this.masonry = new PPMasonry( {
					container: this.elements.$testimonials[0],
					itemSelector: '.pp-grid-item-wrap',
				} );

				this.masonry.observeResize();

				// Measure once images are loaded, then keep it in sync as (lazy) images resolve.
				this.elements.$testimonials.imagesLoaded( function () {
					self.masonry.setReady();
					self.masonry.layout();
				} );

				this.elements.$testimonials.find('img').on('load', function () {
					self.masonry.layoutIfReady();
				} );
			}

			onElementChange() {
				if ( this.masonry && 'masonry' === this.elements.$testimonials.data('layout') ) {
					setTimeout( () => this.masonry.layout() );
				}
			}

			onDestroy() {
				if ( this.masonry ) {
					this.masonry.destroy();
				}

				if ( super.onDestroy ) {
					super.onDestroy();
				}
			}

			async initSlider() {
				const Swiper = elementorFrontend.utils.swiper;
				this.swiper = await new Swiper( this.elements.$testimonials, this.getSwiperOptions() );
			}

			applyVerticalHeight() {
				if ( ! this.swiper || 'vertical' !== this.swiper.params.direction ) {
					return;
				}

				const $container = this.elements.$testimonials;
				const $slides    = this.elements.$swiperSlide;
				const swiper     = this.swiper;

				const recalc = () => {
					$container.css( 'height', '' );
					$slides.css( 'height', '' );

					let maxHeight = 0;
					$slides.each( function () {
						const h = $( this ).outerHeight();
						if ( h > maxHeight ) {
							maxHeight = h;
						}
					} );

					if ( ! maxHeight ) {
						return;
					}

					const spv = parseFloat( swiper.params.slidesPerView ) || 1;
					const spb = parseFloat( swiper.params.spaceBetween ) || 0;
					const totalHeight = ( maxHeight * spv ) + ( spb * Math.max( 0, spv - 1 ) );

					$container.css( 'height', totalHeight + 'px' );
					swiper.update();
				};

				$container.imagesLoaded( recalc );

				swiper.on( 'resize', recalc );
				swiper.on( 'breakpoint', recalc );
			}

			thumbsNav() {
				const thumbsNav = this.$element.find( '.pp-testimonials-thumb-item-wrap' );
				const swiper    = this.swiper;

				thumbsNav.removeClass('pp-active-slide');
				thumbsNav.eq(0).addClass('pp-active-slide');

				swiper.on( 'slideChange', function () {
					thumbsNav.removeClass('pp-active-slide');
					thumbsNav.eq( swiper.realIndex ).addClass('pp-active-slide');
				});

				thumbsNav.each( function ( index ) {
					$(this).on( 'click', function ( e ) {
						e.preventDefault();
						swiper.slideToLoop ? swiper.slideToLoop( index ) : swiper.slideTo( index );
					});
				});
			}

			widgetResize() {
				const testimonialsWrap = this.elements.$testimonialsWrap;
				const swiper           = this.swiper;

				if ( elementorFrontend.isEditMode ) {
					if ( 'undefined' !== typeof ResizeObserver && testimonialsWrap[0] ) {
						const ro = new ResizeObserver( function() {
							swiper.update();
						});
						ro.observe( testimonialsWrap[0] );
					}
				}
			}

			ppWidgetUpdate() {
				const swiper = this.swiper;
				const $triggers = [
					'ppe-tabs-switched',
					'ppe-toggle-switched',
					'ppe-accordion-switched',
					'ppe-popup-opened',
				];

				$triggers.forEach(function(trigger) {
					if ( 'undefined' !== typeof trigger ) {
						$(document).on(trigger, function(e, wrap) {
							if ( 'ppe-popup-opened' == trigger ) {
								wrap = $('.pp-modal-popup-' + wrap);
							}

							if ( wrap.find( '.pp-testimonials' ).length > 0 ) {
								setTimeout(function() {
									swiper.update();
								}, 100);
							}
						});
					}
				});
			}
		}

		elementorFrontend.elementsHandler.attachHandler( 'pp-testimonials', TestimonialsWidget );
	} );
})(jQuery);
