document.addEventListener('DOMContentLoaded', () => {
    const swiperType = 'swiper';
    const swiperRightType = 'swiper-right';
    const swiperLeftType = 'swiper-left';
    const swiperContentType = 'swiper-content';
    const swiperSlideType = 'swiper-slide';

    const swipers = document.querySelectorAll(`[data-type=${swiperType}]`);
    for (let i = 0; i < swipers.length; i++) {
        const swiper = swipers[i];

        const right = swiper.querySelector(`[data-type=${swiperRightType}]`);
        const left = swiper.querySelector(`[data-type=${swiperLeftType}]`);
        const content = swiper.querySelector(`[data-type=${swiperContentType}]`);

        const count = Number(content.dataset.count) ?? 1;
        const isCircular = swiper.dataset.circular === 'true';
        let index = 0;
        let isTransition = false;

        const slides = swiper.querySelectorAll(`[data-type=${swiperSlideType}]`);
        if (slides.length < count + 1) continue;

        const goSlide = (newIndex, animated = true, round = true) => {
            if (!animated) content.dataset.animate = 'false';
            if (isTransition) return;

            isTransition = animated;
            index = round ? Math.round(newIndex) : newIndex;
            const end = (slides.length - count) * slides[0].clientWidth;
            let transform = index * slides[0].clientWidth;
            if (transform < 0) transform = transform / 2;
            if (transform > end) transform = (transform + end) / 2;
            content.style.transform = `translate3d(${transform}px, 0, 0)`;
            content.offsetHeight; // Reflow trick
            content.dataset.animate = 'true';
        }

        if (!isCircular) {
            right.addEventListener('click', async () => {
                goSlide(index - 1);
            });

            left.addEventListener('click', async () => {
                goSlide(index + 1);
            });

            content.addEventListener("transitionend", (e) => {
                if (e.target !== content) return;
                isTransition = false;

                left.disabled = (index + count + 1) > slides.length;
                right.disabled = index < 1;
            });

            left.disabled = (count + 1) > slides.length;
        } else {
            content.prepend(slides[slides.length - 1].cloneNode(true));
            for (let j = 0; j < count; j++) {
                content.appendChild(slides[j].cloneNode(true));
            }

            goSlide(count, false);

            right.addEventListener('click', async () => {
                goSlide(index - 1);
            });

            left.addEventListener('click', async () => {
                goSlide(index + 1);
            });

            content.addEventListener("transitionend", (e) => {
                if (e.target !== content) return;
                isTransition = false;

                if (index === 0) {
                    goSlide(slides.length, false);
                } else if (index === slides.length + 1) {
                    goSlide(1, false);
                }
            });

            setInterval(() => {
                goSlide(index + 1);
            }, 5000);
        }

        // Drag
        content.style.userSelect = 'none';
        content.style.touchAction = 'pan-x';

        let currentPos = 0;
        let isDragging = false;

        const drag = (e) => {
            isDragging = true;
            let position = e.clientX ?? e.touches[0].pageX;

            let transformPixel = position - currentPos;
            currentPos = position;

            let difIndex = transformPixel / (content.scrollWidth / slides.length);
            let newIndex = index + difIndex;

            goSlide(newIndex, false, false);
        }

        const dragEnd = () => {
            setTimeout(() => isDragging = false, 200);

            if (index < 0)
                goSlide(0);
            if (index > slides.length - count)
                goSlide(slides.length - count);

            document.removeEventListener('pointermove', drag);
            document.removeEventListener('pointerup', dragEnd);
            document.removeEventListener('pointercancel', dragEnd);
            document.removeEventListener('touchmove', drag);
            document.removeEventListener('touchend', dragEnd);
        }

        slides.forEach(slide => slide.addEventListener('click', (e) => {
            if (isDragging) e.preventDefault();
        }));

        const dragStart = (e) => {
            currentPos = e.clientX ?? e.touches[0].pageX;

            document.addEventListener('pointermove', drag);
            document.addEventListener('pointerup', dragEnd);
            document.addEventListener('pointercancel', dragEnd);
            document.addEventListener('touchmove', drag);
            document.addEventListener('touchend', dragEnd);

            e.preventDefault();
        }

        content.addEventListener('pointerdown', dragStart);
        // Touch
        content.addEventListener('touchstart', dragStart);
    }
});