/*Simple Horizontal Slider 
selector: class of the container af the slider  (default 'slider')
Block with class slider-track: container of slides
Block with class slide: blocks to be slided
 
*/
class SimpleSlider {
    constructor(selector, options = {}) {
        // Select DOM elements
        selector = selector.trim()==0?'slider': selector;
        this.container = document.querySelector(`.${selector}`);
        this.track = this.container.querySelector('.slider-track');
        this.slides = Array.from(this.track.children);
        this.dotsContainer = this.container.querySelector('.slider-dots');

        // Set initial values and options
        this.currentIndex = 1;
        this.startIndex = 1;
        this.slidesToShow = options.slidesToShow || 1;
        this.autoPlay = options.autoPlay || false;
        this.autoPlayInterval = options.autoPlayInterval || 3000;
        this.dragSlide = 'transform ' + (options.dragTime || 500) + 'ms ease';
        this.dragTreshHold = 4;     

        // Dragging related properties
        this.isDragging = false;
        this.startPos = 0;
        this.currentTranslate = 0;
        this.prevTranslate = 0;
        this.animationID = null;

        // Slider dimensions
        this.groupWidth = 0;
        this.slidesGroups = 0;
 
        // Initialize the slider
        this.init();
    }

    // Initialize slider components
    init() {
        this.checkResponsive();
        this.cloneSlides();
        this.setupSlider();
        this.createDots();
        this.addEventListeners();
        if (this.autoPlay) this.startAutoPlay();
    }

    // Clone slides groups (first and last one)  for infinite effect
    cloneSlides() {
        const firstClone = this.slides.slice(0, this.slidesToShow).map(slide => slide.cloneNode(true));
        const lastClone = this.slides.slice(-this.slidesToShow).map(slide => slide.cloneNode(true));

        firstClone.forEach(clone => {clone.classList.add('clone');this.track.appendChild(clone)});
        lastClone.reverse().forEach(clone => {clone.classList.add('clone'); this.track.prepend(clone)});

        this.slides = Array.from(this.track.children);
    }

    // Check and adjust for responsive design
    //Max Width is the width of the slider container
    checkResponsive() {
        this.slideWidth = parseInt(getComputedStyle(this.slides[0]).width);
        let maxWidth = parseInt(getComputedStyle(this.container).width); 
        if (this.slidesToShow * this.slideWidth >= maxWidth) {
            this.slidesToShow = Math.floor(maxWidth / this.slideWidth);
        }
    }

    // Set up initial slider layout
    setupSlider() {
        this.track.style.display = 'flex';
        let width = this.slideWidth;
        this.container.style.width = (parseInt(width) * this.slidesToShow) + 'px';
        this.groupWidth = parseInt(width) * this.slidesToShow;
        this.currentIndex = 1;
        this.startIndex = 1;
        this.slidesGroups = Math.ceil((this.slides.length - this.slidesToShow * 2) / this.slidesToShow);
        this.updateSlider(false);
        this.container.classList.add("loaded");
    }

    // Create navigation dots
    createDots() {
        const fragment = document.createDocumentFragment();
        for (let i = 0; i < this.slidesGroups; i++) {
            let dot = document.createElement('span');
            dot.classList.add('dot');
            dot.dataset.index = i;
            fragment.appendChild(dot);
        }
        this.dotsContainer.appendChild(fragment);
        this.updateDots();
    }

    // Add event listeners for user interaction
    addEventListeners() {
        this.dotsContainer.querySelectorAll('.dot').forEach(dot => {
            dot.addEventListener('click', () => this.goToSlide(parseInt(dot.dataset.index)));
        });

        this.track.addEventListener('mousedown', (e) => this.dragStart(e));
        this.track.addEventListener('touchstart', (e) => this.dragStart(e));
        this.track.addEventListener('transitionend', (e) => this.resetSlider(e))
        window.addEventListener('mousemove', (e) => this.drag(e));
        window.addEventListener('touchmove', (e) => this.drag(e));
        window.addEventListener('mouseup', (e) => this.dragEnd(e));
        window.addEventListener('touchend', (e) => this.dragEnd(e));
        window.addEventListener('mouseleave', (e) => this.dragEnd(e));
    }

    // Start dragging
    dragStart(e) {
        if (e.type === 'touchstart') {
            this.startPos = e.touches[0].clientX;

        } else {
            this.startPos =  e.clientX;
            e.preventDefault();
        }
        this.isDragging = true;
        this.startIndex = this.currentIndex;
        this.track.style.transition = 'none';
        this.animationID = requestAnimationFrame(this.animation.bind(this));
    }
 
    // Handle dragging
    drag(e) {
        if (!this.isDragging) return;
        const currentPosition = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
        const diff = currentPosition - this.startPos;
        this.currentTranslate = -this.startIndex * this.groupWidth + diff;
    }
 
    // End dragging
    dragEnd() {
        this.isDragging = false;
        cancelAnimationFrame(this.animationID);
        const movedBy = this.currentTranslate + this.startIndex * this.groupWidth;
        if (Math.abs(movedBy) > this.groupWidth / this.dragTreshHold) {
            if (movedBy < 0) {
                this.currentIndex = this.startIndex + 1;
            } else {
                this.currentIndex = this.startIndex - 1;
            }
        } else {
            this.currentIndex = this.startIndex;
        }
        this.updateSlider(true);
    }

    // Update slider position
  
    updateSlider(withTransition = true) {
        if (withTransition) {
            this.track.style.transition = this.dragSlide;
        } else {
            this.track.style.transition = 'none';
        }
        this.currentTranslate = -this.currentIndex * this.groupWidth;
        this.prevTranslate = this.currentTranslate;
        this.track.style.transform = `translateX(${this.currentTranslate}px)`;
 
        this.updateDots();
    }

  
    // Reset slider for infinite effect (end slide transition event)
 
    resetSlider() {
        if (this.currentIndex <= 0) {
            this.currentIndex = this.slidesGroups;
            this.track.style.transition = 'none';
            this.currentTranslate = -this.currentIndex * this.groupWidth;
            this.track.style.transform = `translateX(${this.currentTranslate}px)`;
        } else if (this.currentIndex > this.slidesGroups) {
            this.currentIndex = 1;
            this.track.style.transition = 'none';
            this.currentTranslate = -this.currentIndex * this.groupWidth;
            this.track.style.transform = `translateX(${this.currentTranslate}px)`;
        }
    }
 
    // Animation frame for smooth dragging
    animation() {
      this.track.style.transform = `translateX(${this.currentTranslate}px)`;
      if (this.isDragging) requestAnimationFrame((e)=>this.animation(e));
    }

    // Update active dot
    updateDots() {
        const activeDotIndex = (this.currentIndex - 1 + this.slidesGroups) % this.slidesGroups;
        this.dotsContainer.querySelectorAll('.dot').forEach((dot, index) => {
            dot.classList.toggle('active', index === activeDotIndex);
        });
    }

    // Go to specific slide
    goToSlide(index) {
        this.currentIndex = index + 1;
        this.updateSlider();
    }
  
    prevSlide() {
        this.currentIndex--;
        this.updateSlider();
    }
  
    nextSlide() {
      this.currentIndex++;
      this.updateSlider();
      }
    // Start auto play
    startAutoPlay() {
        const autoPlayAnimation = (timestamp) => {
            if (!this.lastAutoPlayTime) this.lastAutoPlayTime = timestamp;
            const elapsed = timestamp - this.lastAutoPlayTime;

            if (elapsed >= this.autoPlayInterval) {
                this.nextSlide();
                this.lastAutoPlayTime = timestamp;
            }

            this.autoPlayAnimationId = requestAnimationFrame(autoPlayAnimation);
        };

        this.autoPlayAnimationId = requestAnimationFrame(autoPlayAnimation);
    }

    stopAutoPlay() {
        cancelAnimationFrame(this.autoPlayAnimationId);
        this.lastAutoPlayTime = null;
    }
}

// Initialize the slider
window.addEventListener('load', () => {
    new SimpleSlider('', { slidesToShow: 2, autoPlay: true, autoPlayInterval: 3000, dragTime: 800 });
});
