jQuery( function ( $ ) {
	/**
	 * Start carousel autoplay once the module enters the viewport (Waypoint or IntersectionObserver).
	 *
	 * @param {Element}            el      Element to observe (carousel wrap).
	 * @param {string|undefined}   offset  Waypoint offset (e.g. `50%`).
	 * @param {function(): void}   startFn Calls Swiper autoplay.start().
	 * @return {void}
	 */
	function bindViewportAutoplay( el, offset, startFn ) {
		const resolvedOffset =
			offset && String( offset ).trim() !== '' ? String( offset ) : '50%';
		const Wp = typeof window !== 'undefined' ? window.Waypoint : undefined;

		if ( typeof Wp !== 'undefined' ) {
			// eslint-disable-next-line no-new
			new Wp( {
				element: el,
				handler() {
					startFn();
					this.destroy();
				},
				offset: resolvedOffset,
			} );
			return;
		}

		if ( typeof IntersectionObserver !== 'undefined' ) {
			let rootMargin = '0px 0px -15% 0px';
			const m = resolvedOffset.match( /^(\d+)%$/ );
			if ( m ) {
				const p = Math.max(
					0,
					Math.min( 100, parseInt( m[ 1 ], 10 ) )
				);
				rootMargin = '0px 0px -' + ( 100 - p ) + '% 0px';
			}
			const obs = new IntersectionObserver(
				function ( entries, o ) {
					entries.forEach( function ( e ) {
						if ( e.isIntersecting ) {
							startFn();
							o.unobserve( e.target );
						}
					} );
				},
				{ root: null, rootMargin, threshold: 0 }
			);
			obs.observe( el );
			return;
		}

		startFn();
	}

	$( '.dsm_post_carousel' ).each( function ( index, item ) {
		const $wrap = $( item );
		const $carouselRoot = $wrap.find( '.dsm-post-carousel' ).first();
		const carouselEl = $carouselRoot[ 0 ];
		const data = $carouselRoot.data() || {};
		const container = item.querySelector(
			'.swiper-container.dsm-post-carousel-container'
		);

		if ( ! container || typeof Swiper === 'undefined' ) {
			return;
		}

		/**
		 * Read slidesPerGroup from data-* on the carousel root (avoid jQuery .data() key mismatches
		 * for concatenated names like data-slidetoscrolldesktop).
		 *
		 * @param {'desktop'|'tablet'|'phone'} breakpoint Which responsive value to use.
		 * @return {number}
		 */
		function readSlideToScroll( breakpoint ) {
			if ( ! carouselEl ) {
				return 1;
			}
			const hyphen = 'data-slide-to-scroll-' + breakpoint;
			const legacy =
				breakpoint === 'desktop'
					? 'data-slidetoscrolldesktop'
					: breakpoint === 'tablet'
					? 'data-slidetoscrolltablet'
					: 'data-slidetoscrollphone';
			const raw =
				carouselEl.getAttribute( hyphen ) ||
				carouselEl.getAttribute( legacy );
			if ( raw !== null && raw !== '' ) {
				const n = parseInt( raw, 10 );
				if ( ! isNaN( n ) && n >= 1 ) {
					return n;
				}
			}
			const ds = carouselEl.dataset || {};
			const camel =
				breakpoint === 'desktop'
					? ds.slideToScrollDesktop
					: breakpoint === 'tablet'
					? ds.slideToScrollTablet
					: ds.slideToScrollPhone;
			if ( camel !== undefined && camel !== '' ) {
				const n = parseInt( String( camel ), 10 );
				if ( ! isNaN( n ) && n >= 1 ) {
					return n;
				}
			}
			return 1;
		}

		const NavigationPrevButton = item.querySelector(
			'.swiper-button-prev'
		);
		const NavigationNextButton = item.querySelector(
			'.swiper-button-next'
		);

		const paginationContainer = item.querySelector( '.swiper-pagination' );

		const navigation = {
			nextEl: NavigationNextButton,
			prevEl: NavigationPrevButton,
		};

		const pagination = {
			el: paginationContainer,
			clickable: true,
			type:
				'progressbar' !== data.pagiButtonStyle
					? 'bullets'
					: 'progressbar',
			dynamicBullets: 'dynamic' === data.pagiButtonStyle ? true : false,
		};

		const loopInfinite =
			data.multiRow === 'on'
				? false
				: data.loop === true ||
				  data.loop === 1 ||
				  data.loop === '1' ||
				  data.loop === 'on';

		const centeredSlides = data.centered === 'on';

		const isCubeOrFlip =
			'cube' === data.effect || 'flip' === data.effect;

		const slidesPerGroupDesktop = isCubeOrFlip
			? 1
			: readSlideToScroll( 'desktop' );
		const slidesPerGroupTablet = isCubeOrFlip
			? 1
			: readSlideToScroll( 'tablet' );
		const slidesPerGroupPhone = isCubeOrFlip
			? 1
			: readSlideToScroll( 'phone' );

		const DSM_PostCarousel = new Swiper( container, {
			direction: data.orientation,
			effect: data.effect,
			coverflowEffect: {
				slideShadows: data.effectShadows === 'on' ? true : false,
				rotate: data.effectCoverflowRotate,
				depth: data.effectCoverflowDepth,
			},
			flipEffect: {
				rotate: 30,
				slideShadows: data.effectShadows === 'on' ? true : false,
			},
			cubeEffect: {
				slideShadows: data.effectShadows === 'on' ? true : false,
				shadow: data.effectShadows === 'on' ? true : false,
				shadowOffset: 20,
				shadowScale: 0.94,
			},
			speed: Number( data.speed ),
			loop: centeredSlides ? true : loopInfinite,
			autoplay: {
				enabled: false,
				delay: data.autoplayspeed,
				disableOnInteraction: false,
			},
			mousewheel: data.mousewheel === 'on' ? true : false,
			setWrapperSize:
				'cube' === data.effect || 'flip' === data.effect
					? false
					: true,
			observer: true,
			observeParents: true,
			observeSlideChildren: true,
			slideClass: 'dsm-post-carousel-item',
			wrapperClass: 'dsm-post-carousel-wrapper',
			navigation,
			pagination,
			centeredSlides,
			grid: {
				rows: data.multiRow === 'on' ? Number( data.row ) : 1,
				fill: 'row',
			},
			grabCursor: data.grab === 'on' ? true : false,
			allowTouchMove: data.touchMove === 'off' ? true : false,
			slidesPerGroup: slidesPerGroupDesktop,
			a11y: {
				enabled: false,
				slideRole: 'group',
			},
			breakpoints: {
				320: {
					slidesPerView:
						'cube' === data.effect || 'flip' === data.effect
							? 1
							: Number( data.columnsphone ),
					slidesPerGroup: slidesPerGroupPhone,
					spaceBetween:
						'cube' === data.effect || 'flip' === data.effect
							? 0
							: Number( data.spacingphone ),
					grid: {
						rows:
							data.multiRow === 'on'
								? Number( data.rowsphone )
								: 1,
						fill: 'row',
					},
				},
				480: {
					slidesPerView:
						'cube' === data.effect || 'flip' === data.effect
							? 1
							: Number( data.columnsphone ),
					slidesPerGroup: slidesPerGroupPhone,
					spaceBetween:
						'cube' === data.effect || 'flip' === data.effect
							? 0
							: Number( data.spacingphone ),
					grid: {
						rows:
							data.multiRow === 'on'
								? Number( data.rowsphone )
								: 1,
						fill: 'row',
					},
				},
				768: {
					slidesPerView:
						'cube' === data.effect || 'flip' === data.effect
							? 1
							: Number( data.columnstablet ),
					slidesPerGroup: slidesPerGroupTablet,
					spaceBetween:
						'cube' === data.effect || 'flip' === data.effect
							? 0
							: Number( data.spacingtablet ),
					grid: {
						rows:
							data.multiRow === 'on'
								? Number( data.rowstablet )
								: 1,
						fill: 'row',
					},
				},
				981: {
					slidesPerView:
						'cube' === data.effect || 'flip' === data.effect
							? 1
							: Number( data.columnsdesktop ),
					slidesPerGroup: slidesPerGroupDesktop,
					spaceBetween:
						'cube' === data.effect || 'flip' === data.effect
							? 0
							: Number( data.spacing ),
					grid: {
						rows:
							data.multiRow === 'on' ? Number( data.row ) : 1,
						fill: 'row',
					},
				},
			},
		} );

		if ( data.pauseOnHover === 'on' ) {
			$wrap.on( 'mouseenter', function () {
				DSM_PostCarousel.autoplay.stop();
			} );
			$wrap.on( 'mouseleave', function () {
				DSM_PostCarousel.autoplay.start();
			} );
		}
		const autoplayOn =
			data.autoplay === 'on' ||
			data.autoplay === true ||
			data.autoplay === 1;
		if ( autoplayOn ) {
			bindViewportAutoplay( item, data.autoplayViewport, function () {
				DSM_PostCarousel.autoplay.start();
			} );
		}
	} );
} );
