/* globals GalleryYTPlayer, YT, GalleryVKPlayer, VK */

import { getScrollbarWidth } from '@advdominion/get-scrollbar-width';

const getYTPlayer = () => {
    const script = document.createElement('script');
    script.src = 'https://www.youtube.com/player_api';
    script.async = true;
    document.body.append(script);
};

const getVKPlayer = () => {
    const script = document.createElement('script');
    script.src = 'https://vk.com/js/api/videoplayer.js';
    script.async = true;
    document.body.append(script);
};

const playVideo = (slide) => {
    const youtube = slide.querySelector('.advdominion-lg__video_youtube');
    const vk = slide.querySelector('.advdominion-lg__video_vk');
    const rt = slide.querySelector('.advdominion-lg__video_rt');

    if (youtube) {
        if (slide.YTPlayer) {
            if (slide.classList.contains('swiper-slide-active')) {
                slide.YTPlayer.playVideo();
            }
        } else if (window.YT) {
            if (GalleryYTPlayer.state) {
                slide.YTPlayer = new YT.Player(youtube, {
                    videoId: youtube.dataset.id,
                    events: {
                        onReady(event) {
                            if (slide.classList.contains('swiper-slide-active')) {
                                event.target.playVideo();
                            }
                        },
                    },
                });
            } else {
                GalleryYTPlayer.addListener(() => {
                    playVideo(slide);
                });
            }
        } else {
            getYTPlayer();
            GalleryYTPlayer.addListener(() => {
                playVideo(slide);
            });
        }
    } else if (vk) {
        if (slide.VKPlayer) {
            if (slide.classList.contains('swiper-slide-active')) {
                slide.VKPlayer.play();
            }
        } else if (window.VK?.VideoPlayer) {
            if (GalleryVKPlayer.state) {
                slide.VKPlayer = VK.VideoPlayer(vk);
                slide.VKPlayer.on('inited', () => {
                    if (slide.classList.contains('swiper-slide-active')) {
                        slide.VKPlayer.play();
                    }
                });
            } else {
                GalleryVKPlayer.addListener(() => {
                    playVideo(slide);
                });
            }
        } else {
            getVKPlayer();
            GalleryVKPlayer.addListener(() => {
                playVideo(slide);
            });
        }
    } else if (rt) {
        const videoId = /embed\/(\w+)/.exec(rt.getAttribute('src'))?.[1];
        const checkInterval = setInterval(() => {
            if (window.GalleryRTPlayer) {
                if (window.GalleryRTPlayer.has(videoId)) {
                    clearInterval(checkInterval);
                    if (slide.classList.contains('swiper-slide-active')) {
                        rt.contentWindow.postMessage(
                            JSON.stringify({
                                type: 'player:play',
                                data: {},
                            }),
                            '*',
                        );
                    }
                }
            } else {
                clearInterval(checkInterval);
            }
        }, 100);
        slide.checkInterval = checkInterval;
    }
};

const pauseVideo = (slide) => {
    const youtube = slide.querySelector('.advdominion-lg__video_youtube');
    const vk = slide.querySelector('.advdominion-lg__video_vk');
    const rt = slide.querySelector('.advdominion-lg__video_rt');

    if (youtube && slide.YTPlayer) {
        slide.YTPlayer.pauseVideo();
    } else if (vk && slide.VKPlayer) {
        slide.VKPlayer.pause();
    } else if (rt) {
        rt.contentWindow.postMessage(
            JSON.stringify({
                type: 'player:pause',
                data: {},
            }),
            '*',
        );
    }
};

const setVideoSize = (gallery) => {
    const items = gallery.querySelectorAll('.advdominion-lg__video-wrapper');
    items[0].style.cssText = '';
    let height = (items[0].getBoundingClientRect().width * 9) / 16;
    let width = '';
    if (height > items[0].getBoundingClientRect().height) {
        height = items[0].getBoundingClientRect().height;
        width = `${(height * 16) / 9}px`;
    }
    for (const item of items) {
        item.style.cssText = `
            height: ${height}px;
            width: ${width};
        `;
    }
};

const hide = async (duration = 500, easing = 'linear') => {
    const gallery = document.body.querySelector('.advdominion-lg');

    await gallery.animate([{ opacity: 1 }, { opacity: 0 }], {
        duration,
        easing,
    }).finished;

    // Очищаем интервалы проверки для видео
    for (const slide of gallery.querySelectorAll('.advdominion-lg__item_video')) {
        if (slide.checkInterval) {
            clearInterval(slide.checkInterval);
        }
    }

    gallery.remove();
    delete window.GalleryRTPlayer;

    document.body.style.cssText = `
        overflow: '';
        margin-right: '';
    `;
};

const show = async (duration = 500, easing = 'linear') => {
    const gallery = document.body.querySelector('.advdominion-lg');

    document.body.style.cssText = `
        overflow: hidden;
        margin-right: ${getScrollbarWidth()}px
    `;

    await gallery.animate([{ opacity: 0 }, { opacity: 1 }], {
        duration,
        easing,
    }).finished;
};

const init = async (items = [], options = {}, index = 0) => {
    const [{ default: Swiper }, { Navigation, Pagination }] = await Promise.all([
        import('swiper'),
        import('swiper/modules'),
    ]);

    const isVideoInGallery = {
        yt: false,
        vk: false,
        rt: false,
    };
    items = items.map(({ url: item, caption }) => {
        if (/youtube\.com\/watch\?v=/.test(item)) {
            isVideoInGallery.yt = true;
            return `
                <div class="advdominion-lg__item advdominion-lg__item_video swiper-slide">
                    <div class="advdominion-lg__video-wrapper">
                        <div
                            class="advdominion-lg__video advdominion-lg__video_youtube"
                            data-id="${/v=([\w-]+)/i.exec(item)[1]}">
                            Загрузка YouTube-плеера...
                        </div>
                    </div>
                    ${caption ? `<div class="advdominion-lg__caption">${caption}</div>` : ''}
                </div>
            `;
        } else if (/(?:vkvideo\.ru|vk\.com)\/video/.test(item)) {
            isVideoInGallery.vk = true;
            const videoId = /(?:vkvideo\.ru|vk\.com)\/video(-?\d+)_(\d+)/.exec(item);
            if (videoId === null) {
                return `
                    <div class="advdominion-lg__item advdominion-lg__item_video swiper-slide">
                        <div class="advdominion-lg__video-wrapper">
                            <div class="advdominion-lg__video advdominion-lg__video_vk">
                                Ошибка при загрузке VK-плеера
                            </div>
                        </div>
                        ${caption ? `<div class="advdominion-lg__caption">${caption}</div>` : ''}
                    </div>
                `;
            }
            return `
                <div class="advdominion-lg__item advdominion-lg__item_video swiper-slide">
                    <div class="advdominion-lg__video-wrapper">
                        <iframe
                            class="advdominion-lg__video advdominion-lg__video_vk"
                            src="https://vkvideo.ru/video_ext.php?oid=${videoId[1]}&id=${videoId[2]}&hd=4&js_api=1"
                            allow="autoplay; encrypted-media; fullscreen; picture-in-picture; screen-wake-lock;">
                        </iframe>
                    </div>
                    ${caption ? `<div class="advdominion-lg__caption">${caption}</div>` : ''}
                </div>
            `;
        } else if (/rutube\.ru/.test(item)) {
            isVideoInGallery.rt = true;
            const videoId = /video\/(\w+)/.exec(item);
            if (videoId === null) {
                return `
                    <div class="advdominion-lg__item advdominion-lg__item_video swiper-slide">
                        <div class="advdominion-lg__video-wrapper">
                            <div class="advdominion-lg__video advdominion-lg__video_rt">
                                Ошибка при загрузке RuTube-плеера
                            </div>
                        </div>
                        ${caption ? `<div class="advdominion-lg__caption">${caption}</div>` : ''}
                    </div>
                `;
            }
            return `
                <div class="advdominion-lg__item advdominion-lg__item_video swiper-slide">
                    <div class="advdominion-lg__video-wrapper">
                        <iframe
                            class="advdominion-lg__video advdominion-lg__video_rt"
                            src="https://rutube.ru/play/embed/${videoId[1]}"
                            allow="autoplay; encrypted-media; fullscreen; picture-in-picture; screen-wake-lock;">
                        </iframe>
                    </div>
                    ${caption ? `<div class="advdominion-lg__caption">${caption}</div>` : ''}
                </div>
            `;
        }
        return `
            <div class="advdominion-lg__item swiper-slide">
                <img class="advdominion-lg__image" src="${item}" alt="" loading="lazy">
                ${caption ? `<div class="advdominion-lg__caption">${caption}</div>` : ''}
            </div>
        `;
    });

    if (isVideoInGallery.yt && !window.GalleryYTPlayer) {
        window.GalleryYTPlayer = {
            state: false,
            get init() {
                return this.state;
            },
            set init(val) {
                this.state = val;
                for (const i of this.callback) {
                    i(val);
                }
            },
            callback: [],
            addListener(callback) {
                this.callback.push(callback);
            },
        };

        window.onYouTubeIframeAPIReady = () => {
            window.GalleryYTPlayer.init = true;
        };
    }

    if (isVideoInGallery.vk && !window.GalleryVKPlayer) {
        window.GalleryVKPlayer = {
            state: false,
            get init() {
                return this.state;
            },
            set init(val) {
                this.state = val;
                for (const i of this.callback) {
                    i(val);
                }
            },
            callback: [],
            addListener(callback) {
                this.callback.push(callback);
            },
        };

        const checkInterval = setInterval(() => {
            if (window.VK?.VideoPlayer) {
                clearInterval(checkInterval);
                window.GalleryVKPlayer.init = true;
            }
        }, 100);
    }

    if (isVideoInGallery.rt) {
        window.GalleryRTPlayer = new Set();
        window.addEventListener('message', (event) => {
            if (event.origin.includes('rutube.ru') && typeof event.data === 'string') {
                const message = JSON.parse(event.data);
                if (message.type === 'player:ready') {
                    window.GalleryRTPlayer.add(message.data.videoId);
                }
            }
        });
    }

    document.body.insertAdjacentHTML(
        'beforeend',
        `
            <div class="advdominion-lg">
                <button class="advdominion-lg__close" type="button">
                    <svg class="advdominion-lg__close-icon"><use href="${options.icons.close}" /></svg>
                </button>
                <div class="advdominion-lg__container swiper">
                    <div class="advdominion-lg__wrapper swiper-wrapper">
                        ${items.join('')}
                    </div>
                    ${options.pagination || ''}
                    ${options.navigation || ''}
                </div>
            </div>
        `,
    );

    const gallery = document.body.querySelector('.advdominion-lg');

    gallery.querySelector('.advdominion-lg__container').style.cssText = `
        visibility: hidden;
    `;

    await show(options?.animation?.show?.duration, options?.animation?.show?.easing);

    const swiper = new Swiper(
        gallery.querySelector('.advdominion-lg__container'),
        Object.assign({ init: false, initialSlide: index }, options.swiper, {
            modules: [...new Set([Navigation, Pagination, ...(options.swiper?.modules || [])])],
        }),
    );

    swiper.on('init', function () {
        gallery.querySelector('.advdominion-lg__container').style.cssText = `
            visibility: '';
        `;

        if (this.slides[this.activeIndex].classList.contains('advdominion-lg__item_video')) {
            playVideo(this.slides[this.activeIndex]);
        }

        if (isVideoInGallery.yt || isVideoInGallery.vk || isVideoInGallery.rt) {
            setVideoSize(gallery);
        }
    });

    swiper.on('slideChange', function () {
        setTimeout(() => {
            for (const [index, slide] of Object.entries(this.slides)) {
                if (slide.classList.contains('advdominion-lg__item_video')) {
                    if (Number(index) === this.activeIndex) {
                        playVideo(slide);
                    } else {
                        pauseVideo(slide);
                    }
                }
            }
        });
    });

    swiper.on('resize', function () {
        if (isVideoInGallery.yt || isVideoInGallery.vk || isVideoInGallery.rt) {
            setVideoSize(gallery);
        }
    });

    swiper.init();

    const closeHandler = () => {
        hide(options?.animation?.hide?.duration, options?.animation?.hide?.easing);
    };

    const keydownHandler = (e) => {
        if (e.key === 'Escape') {
            closeHandler();
            document.body.removeEventListener('keydown', keydownHandler);
        }
    };

    gallery.querySelector('.advdominion-lg__close').addEventListener('click', closeHandler);
    document.body.addEventListener('keydown', keydownHandler);
};

export const gallery = (container, options) => {
    const items = [];
    if (options.single) {
        const element = container.children[0];
        items.push({
            url: element.href,
            caption: document.querySelector(element.dataset.galleryCaption)?.textContent,
        });
        container.addEventListener('click', (event) => {
            event.preventDefault();
            init(items, options);
        });
    } else {
        for (const [index, element] of [...container.children].entries()) {
            items.push({
                url: element.href,
                caption: document.querySelector(element.dataset.galleryCaption)?.textContent,
            });
            element.addEventListener('click', (event) => {
                event.preventDefault();
                init(items, options, index);
            });
        }
    }
};
