(($) => {
    window["vidplexGridCarousel"] = (n) => {
        const element = $(`#${n}`);
        const attributes = window[n];

        const body = $("body");

        let swiper = {};

        let playerVars = {
            autoplay: 0,
            disablekb: 1,
            rel: 0,
            iv_load_policy: 3,
            playsinline: 1,
            fs: 0,
        };

        function initializeYoutubeAPI(el, index) {
            const videoId = el.attr("data-video-id");
            const videoRenderer = el.find("div").get(0);

            if (!videoRenderer) return;

            // Prevent duplicate players
            if (videoRenderer.dataset.playerInitialized) return;

            const gridCarouselPlayer = YTPlayerManager.create({
                id: `${n}_${index}`,
                el: videoRenderer,
                videoId,
                options: playerVars,
                onReady: () => {},
                onStateChange: () => {},
            });
        }

        if (
            (attributes.layout === "default" &&
                attributes.displayType === "grid") ||
            attributes.layout === "list"
        ) {
            element.find(".grid__item").each(function (index) {
                const $this = $(this);
                initializeYoutubeAPI($this, index);
            });
        } else if (
            attributes.layout === "default" &&
            attributes.displayType === "carousel"
        ) {
            element.find(".slide__item").each(function (index) {
                const $this = $(this);
                initializeYoutubeAPI($this, index);
            });

            const swiperAttr = {
                slidesPerView: attributes.carousel.slidesPerView?.desktop || 3,
                speed: attributes.carousel.speed,
                spaceBetween: attributes.carousel.spaceBetween?.desktop || 26,
                centeredSlides: attributes.carousel.centeredSlides,
                loop: attributes.carousel.loop,
                navigation: {
                    prevEl: ".swiper-button-prev",
                    nextEl: ".swiper-button-next",
                },
                pagination: {
                    el: ".swiper-pagination",
                },
                breakpoints: {
                    100: {
                        slidesPerView:
                            attributes.carousel.slidesPerView?.mobile || 1,
                        spaceBetween:
                            attributes.carousel.spaceBetween?.mobile ||
                            attributes.carousel.spaceBetween?.desktop,
                    },
                    571: {
                        slidesPerView:
                            attributes.carousel.slidesPerView?.tablet || 2,
                        spaceBetween:
                            attributes.carousel.spaceBetween?.tablet ||
                            attributes.carousel.spaceBetween?.desktop,
                    },
                    1025: {
                        slidesPerView:
                            attributes.carousel.slidesPerView?.desktop,
                        spaceBetween: attributes.carousel.spaceBetween?.desktop,
                    },
                },
            };

            if (attributes.carousel.autoplay.status) {
                swiperAttr.autoplay = { ...attributes.carousel.autoplay };
            } else {
                delete swiperAttr.autoplay;
            }

            swiper = new Swiper(
                element.find(".swiper-container")[0],
                swiperAttr,
            );
        } else if (attributes.isPremium && attributes.layout === "gallery") {
            playerVars = {
                autoplay: attributes.gallery.autoplay ? 1 : 0,
                mute: 1,
                rel: 1,
                controls: attributes.gallery.controls ? 1 : 0,
                iv_load_policy: 3,
                playsinline: 1,
                fs: attributes.gallery.fs ? 1 : 0,
                enablejsapi: 1,
            };

            const playerEl = element.find(".gallery__player");
            const videoId = playerEl.attr("data-video-id");
            const videoRenderer = playerEl.find(".iframe-loader").get(0);

            playerEl.find(".video__thumbnail").addClass("display__none");

            const galleryPlayer = YTPlayerManager.create({
                id: `${n}`,
                el: videoRenderer,
                videoId,
                options: playerVars,
                onReady: () => {},
                onStateChange: () => {},
            });

            element.find(".video__item").each(function () {
                const $this = $(this);

                $this.click(function () {
                    const player = YTPlayerManager.get(n);
                    const currentTime = player.getCurrentTime();
                    const playingVideoId = element
                        .find(".video__item.is-active")
                        .attr("data-video-id");

                    // store the current time for the currently playing video
                    element
                        .find(`.video__item[data-video-id="${playingVideoId}"]`)
                        .attr("data-start-time", currentTime);

                    element.find(".video__item").removeClass("is-active");

                    $this.addClass("is-active");

                    const videoId = $this.attr("data-video-id");
                    const startTime = $this.attr("data-start-time") || 0;

                    YTPlayerManager.replace({ id: n, videoId, startTime });
                });
            });
        }

        /* Popup Video */
        if (
            attributes.isPremium &&
            attributes.layout !== "gallery" &&
            attributes.popup.enabled
        ) {
            if (body.find(".vidplex-grid-carousel__modal").length <= 0) {
                const modal = document.createElement("div");
                modal.className = "vidplex-grid-carousel__modal display__none";
                modal.innerHTML = `
					<div class="modal__overlay"></div>
					<i class="close__icon">
						<svg fill="currentColor" width="20" height="20" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
							<path d="M10.9449 9.66003C11.3049 10.02 11.3049 10.58 10.9449 10.94C10.7649 11.12 10.5449 11.2 10.3049 11.2C10.0649 11.2 9.84493 11.12 9.66493 10.94L6.00492 7.28004L2.34491 10.94C2.16491 11.12 1.94492 11.2 1.70492 11.2C1.46492 11.2 1.24493 11.12 1.06493 10.94C0.704932 10.58 0.704932 10.02 1.06493 9.66003L4.72492 6.00004L1.06493 2.34004C0.704932 1.98004 0.704932 1.42004 1.06493 1.06004C1.42493 0.700037 1.98491 0.700037 2.34491 1.06004L6.00492 4.72003L9.66493 1.06004C10.0249 0.700037 10.5849 0.700037 10.9449 1.06004C11.3049 1.42004 11.3049 1.98004 10.9449 2.34004L7.2849 6.00004L10.9449 9.66003Z" />
						</svg>
					</i>
					<div class="modal__body">
					</div>
				`;
                body.append(modal);
            }

            const $modal = body.find(".vidplex-grid-carousel__modal");

            element.find(".layout__item").each(function () {
                const $this = $(this);
                const videoId = $this.attr("data-video-id");

                $this.click(function () {
                    $modal.addClass(`${n}`);
                    $modal.attr("data-video-id", videoId);
                    body.addClass("overflow__hidden");
                    $modal.removeClass("display__none");

                    if (
                        attributes.layout === "default" &&
                        attributes.displayType === "carousel" &&
                        swiper &&
                        attributes.carousel.autoplay.status
                    ) {
                        swiper.autoplay.stop();
                    }

                    if ($modal.find(".modal__body > div").length <= 0) {
                        const iframeDiv = document.createElement("div");
                        iframeDiv.style.width = "100%";
                        iframeDiv.style.height = "100%";
                        iframeDiv.style.display = "flex";
                        iframeDiv.style.justifyContent = "center";
                        iframeDiv.style.alignItems = "center";
                        iframeDiv.innerHTML = `
							<div class="spinner"></div>
						`;
                        $modal.find(".modal__body").append(iframeDiv);
                    }

                    setTimeout(() => {
                        // Create new player
                        const videoRenderer = $modal.find(".modal__body > div");
                        const player = new YT.Player(videoRenderer[0], {
                            height: "100%",
                            width: "100%",
                            videoId: videoId,
                            playerVars: {
                                autoplay: 0,
                                disablekb: 1,
                                rel: 0,
                                iv_load_policy: 3,
                                playsinline: 1,
                                fs: 0,
                            },
                            events: {
                                onReady: ({ target }) => {},
                            },
                        });
                    }, 500);
                });
            });

            function closeModal() {
                $modal.removeClass(`${n}`);
                $modal.attr("data-video-id", "");
                body.removeClass("overflow__hidden");
                $modal.addClass("display__none");

                if (
                    attributes.layout === "default" &&
                    attributes.displayType === "carousel" &&
                    swiper &&
                    attributes.carousel.autoplay.status
                ) {
                    swiper.autoplay.start();
                }

                // Remove iframe or div
                $modal
                    .find(".modal__body > div, .modal__body > iframe")
                    .remove();
            }

            $modal.find(".close__icon, .modal__overlay").click(function () {
                closeModal();
            });
            $(document).on("keydown", function (e) {
                if (e.key === "Escape" || e.keyCode === 27) {
                    closeModal();
                }
            });
        }

        function initYTForElement($el, index) {
            initializeYoutubeAPI(
                $el,
                element.find(".grid__item.layout__item").length - index,
            );
        }

        /* Ajax Btn */
        const $btnWrap = element.find(".ajax-loader__wrapper");
        const $btn = element.find(".ajax-loader__btn");
        const $loadingEl = element.find(".ajax-loader__btn .loader__element");
        const $btnLabel = element.find(".ajax-loader__btn .btn__label");

        const total = Number(attributes.ajax.total);
        const toFetch = Number(attributes.ajax.toFetch);

        let offset = attributes.ajax.perPage;
        let quota = toFetch > 0 ? Math.ceil(total / toFetch) : 0;

        let data = {
            action: "vidplex_custom_videos_loader",
            nonce: attributes.loaderNonce,
            attributes: JSON.stringify(attributes),
            offset: offset,
            quota: quota,
        };

        if (attributes.videoSource === "channel") {
            offset = attributes.channelVideos.perPage;
            data = {
                ...data,
                action: "vidplex_channel_videos_loader",
                offset: offset,
            };
        }

        if (attributes.ajax.type === "button") {
            $btn.click(function () {
                $.post({
                    url: attributes.ajaxURL,
                    data: data,
                    beforeSend: function () {
                        $btn.addClass("disabled");
                        $btnLabel.addClass("display__none");
                        $loadingEl.removeClass("display__none");
                    },
                    success: function (res) {
                        if (res.success) {
                            if (!res.data.hasNext) {
                                $btnWrap.addClass("display__none");
                            }

                            data = {
                                ...data,
                                offset: res.data.offset,
                                quota: res.data.quota,
                            };

                            const $newContent = $(res.data.render).hide();
                            if (attributes.layout === "gallery") {
                                Object.keys($newContent).map((index) => {
                                    if (
                                        $($newContent[index]).hasClass(
                                            "is-active",
                                        )
                                    ) {
                                        $(
                                            $($newContent[index]).removeClass(
                                                "is-active",
                                            ),
                                        );
                                    }
                                });

                                element
                                    .find(".gallery__sidebar")
                                    .append($newContent);
                                $newContent.fadeIn(400);

                                element
                                    .find(".video__item")
                                    .slice(-Object.keys($newContent).length)
                                    .each(function () {
                                        const $this = $(this);

                                        $this.click(function () {
                                            const player =
                                                YTPlayerManager.get(n);
                                            const currentTime =
                                                player.getCurrentTime();
                                            const playingVideoId = element
                                                .find(".video__item.is-active")
                                                .attr("data-video-id");

                                            // store the current time for the currently playing video
                                            element
                                                .find(
                                                    `.video__item[data-video-id="${playingVideoId}"]`,
                                                )
                                                .attr(
                                                    "data-start-time",
                                                    currentTime,
                                                );

                                            element
                                                .find(".video__item")
                                                .removeClass("is-active");

                                            $this.addClass("is-active");

                                            const videoId =
                                                $this.attr("data-video-id");
                                            const startTime =
                                                $this.attr("data-start-time") ||
                                                0;

                                            YTPlayerManager.replace({
                                                id: n,
                                                videoId,
                                                startTime,
                                            });
                                        });
                                    });
                            } else {
                                element
                                    .find(".display-wrapper")
                                    .append($newContent);
                                $newContent.fadeIn(400);
                            }

                            if (
                                (attributes.layout === "default" &&
                                    attributes.displayType === "grid") ||
                                attributes.layout === "list"
                            ) {
                                const $modal = body.find(
                                    ".vidplex-grid-carousel__modal",
                                );

                                element
                                    .find(".layout__item")
                                    .slice(-res.data.videos.length)
                                    .each((index, el) => {
                                        if (
                                            attributes.isPremium &&
                                            attributes.layout !== "gallery" &&
                                            attributes.popup.enabled
                                        ) {
                                            const $this = $(el);

                                            $this.click(function () {
                                                const videoId =
                                                    $this.attr("data-video-id");

                                                $modal.addClass(`${n}`);
                                                $modal.attr(
                                                    "data-video-id",
                                                    videoId,
                                                );
                                                body.addClass(
                                                    "overflow__hidden",
                                                );
                                                $modal.removeClass(
                                                    "display__none",
                                                );

                                                if (
                                                    $modal.find(
                                                        ".modal__body > div",
                                                    ).length <= 0
                                                ) {
                                                    const iframeDiv =
                                                        document.createElement(
                                                            "div",
                                                        );
                                                    iframeDiv.innerHTML = `
													<div class="spinner"></div>
												`;
                                                    $modal
                                                        .find(".modal__body")
                                                        .append(iframeDiv);
                                                }

                                                setTimeout(() => {
                                                    // Create new player
                                                    const videoRenderer =
                                                        $modal.find(
                                                            ".modal__body > div",
                                                        );
                                                    const player =
                                                        new YT.Player(
                                                            videoRenderer[0],
                                                            {
                                                                height: "100%",
                                                                width: "100%",
                                                                videoId:
                                                                    videoId,
                                                                playerVars: {
                                                                    autoplay: 0,
                                                                    disablekb: 1,
                                                                    rel: 0,
                                                                    iv_load_policy: 3,
                                                                    playsinline: 1,
                                                                    fs: 0,
                                                                },
                                                                events: {
                                                                    onReady: ({
                                                                        target,
                                                                    }) => {},
                                                                },
                                                            },
                                                        );
                                                }, 500);
                                            });
                                        } else {
                                            initYTForElement($(el), index);
                                        }
                                    });
                            }
                        }
                    },
                    error: function () {
                        console.log("Unable to fetch data");
                    },
                    complete: function () {
                        $btn.removeClass("disabled");
                        $btnLabel.removeClass("display__none");
                        $loadingEl.addClass("display__none");
                    },
                });
            });
        } else if (attributes.ajax.type === "scroll" && $btnWrap.length > 0) {
            let hasNext = true;
            let loading = false;
            let nextTriggerOffset = 0;

            function loadMoreItems() {
                if (loading || !hasNext) return;

                loading = true;

                $.post({
                    url: attributes.ajaxURL,
                    data: data,
                    beforeSend: function () {
                        $btnWrap.removeClass("display__none");
                        $loadingEl.removeClass("display__none");
                    },
                    success: function (res) {
                        if (res.success) {
                            hasNext = res.data.hasNext;

                            if (!hasNext) {
                                $btnWrap.addClass("display__none");
                            }

                            data = {
                                ...data,
                                offset: res.data.offset,
                                quota: res.data.quota,
                            };

                            const $newContent = $(res.data.render).hide();
                            if (attributes.layout === "gallery") {
                                Object.keys($newContent).map((index) => {
                                    if (
                                        $($newContent[index]).hasClass(
                                            "is-active",
                                        )
                                    ) {
                                        $(
                                            $($newContent[index]).removeClass(
                                                "is-active",
                                            ),
                                        );
                                    }
                                });

                                element
                                    .find(".gallery__sidebar")
                                    .append($newContent);
                                $newContent.fadeIn(400);

                                element
                                    .find(".video__item")
                                    .slice(-Object.keys($newContent).length)
                                    .each(function () {
                                        const $this = $(this);

                                        $this.click(function () {
                                            const player =
                                                YTPlayerManager.get(n);
                                            const currentTime =
                                                player.getCurrentTime();
                                            const playingVideoId = element
                                                .find(".video__item.is-active")
                                                .attr("data-video-id");

                                            // store the current time for the currently playing video
                                            element
                                                .find(
                                                    `.video__item[data-video-id="${playingVideoId}"]`,
                                                )
                                                .attr(
                                                    "data-start-time",
                                                    currentTime,
                                                );

                                            element
                                                .find(".video__item")
                                                .removeClass("is-active");

                                            $this.addClass("is-active");

                                            const videoId =
                                                $this.attr("data-video-id");
                                            const startTime =
                                                $this.attr("data-start-time") ||
                                                0;

                                            YTPlayerManager.replace({
                                                id: n,
                                                videoId,
                                                startTime,
                                            });
                                        });
                                    });
                            } else {
                                element
                                    .find(".display-wrapper")
                                    .append($newContent);
                                $newContent.fadeIn(400);
                            }

                            const $modal = body.find(
                                ".vidplex-grid-carousel__modal",
                            );

                            if (
                                (attributes.layout === "default" &&
                                    attributes.displayType === "grid") ||
                                attributes.layout === "list" ||
                                attributes.layout === "gallery"
                            ) {
                                element
                                    .find(".layout__item")
                                    .slice(-res.data.videos.length)
                                    .each((index, element) => {
                                        if (
                                            attributes.isPremium &&
                                            attributes.layout !== "gallery" &&
                                            attributes.popup.enabled
                                        ) {
                                            const $this = $(element);

                                            const videoId =
                                                $this.attr("data-video-id");

                                            $this.click(function () {
                                                $modal.addClass(`${n}`);
                                                $modal.attr(
                                                    "data-video-id",
                                                    videoId,
                                                );
                                                body.addClass(
                                                    "overflow__hidden",
                                                );
                                                $modal.removeClass(
                                                    "display__none",
                                                );

                                                if (
                                                    $modal.find(
                                                        ".modal__body > div",
                                                    ).length <= 0
                                                ) {
                                                    const iframeDiv =
                                                        document.createElement(
                                                            "div",
                                                        );
                                                    iframeDiv.innerHTML = `
													<div class="spinner"></div>
												`;
                                                    $modal
                                                        .find(".modal__body")
                                                        .append(iframeDiv);
                                                }

                                                setTimeout(() => {
                                                    // Create new player
                                                    const videoRenderer =
                                                        $modal.find(
                                                            ".modal__body > div",
                                                        );
                                                    const player =
                                                        new YT.Player(
                                                            videoRenderer[0],
                                                            {
                                                                height: "100%",
                                                                width: "100%",
                                                                videoId:
                                                                    videoId,
                                                                playerVars: {
                                                                    autoplay: 0,
                                                                    disablekb: 1,
                                                                    rel: 0,
                                                                    iv_load_policy: 3,
                                                                    playsinline: 1,
                                                                    fs: 0,
                                                                },
                                                                events: {
                                                                    onReady: ({
                                                                        target,
                                                                    }) => {},
                                                                },
                                                            },
                                                        );
                                                }, 500);
                                            });
                                        } else {
                                            initYTForElement($(element), index);
                                        }
                                    });
                            }
                        }
                    },
                    error: function () {
                        console.log("Unable to fetch data");
                    },
                    complete: function () {
                        $btnWrap.addClass("display__none");
                        $loadingEl.addClass("display__none");

                        loading = false;
                    },
                });
            }

            $(window).on("scroll", function () {
                const containerTop = element.offset().top; // top of container relative to document
                const scrollTop = $(window).scrollTop(); // how far page has scrolled
                const windowHeight = $(window).height(); // height of viewport
                const triggerPoint = scrollTop + windowHeight / 2 - 400; // middle of viewport

                if (
                    containerTop <= triggerPoint &&
                    triggerPoint > nextTriggerOffset
                ) {
                    loadMoreItems();
                    // set next trigger below the new content
                    nextTriggerOffset =
                        element.offset().top + element.height() / 2;
                }
            });
        }
    };
})(jQuery);
