'use strict';

import { Controller } from "@hotwired/stimulus";
import { Splide } from '@splidejs/splide';
import '@splidejs/splide/css';

export default class extends Controller {

    static targets = ['progress', 'progressBar']

    static values = {
        type: String,
        peek: Boolean,
    }

    initialize() {
        super.initialize();
        this.splide = null;
    }

    connect() {
        let options = this.defaultOptions;

        if (this.typeValue === 'champagne') {
            options = this.champagneOptions;
        }

        if (this.typeValue === 'timeline') {
            options = this.timelineOptions;
        }

        if (this.typeValue === 'shop-info') {
            options = this.shopInfoOptions;
        }

        if (this.splide) {
            this.splide.destroy(true);
        }

        this.splide = new Splide(this.element, options);

        if (this.typeValue === 'champagne') {
            this.splide.on('mounted refreshed resized updated', () => {
                this.updateProgress();
            });

            this.splide.on('move', (newIndex) => {
                this.updateProgressForIndex(newIndex);
            });

            this.splide.on('moved drag dragging dragged scroll scrolled', () => {
                this.updateProgress();
            });
        }

        this.splide.mount();
    }

    disconnect() {
        if (this.splide) {
            this.splide.destroy(true);
            this.splide = null;
        }
    }

    get champagneOptions() {
        return {
            type: 'slide',
            easing: 'cubic-bezier(.22,1,.36,1)',
            speed: 560,
            pagination: false,
            arrows: false,
            drag: true,
            snap: true,
            focus: 0,
            trimSpace: 'move',
            omitEnd: true,
            waitForTransition: false,
            updateOnMove: true,
            flickPower: 90,
            flickMaxPages: 1,
            dragMinThreshold: {
                mouse: 3,
                touch: 8,
            },
            perPage: 5.25,
            perMove: 1,
            gap: '0.75rem',
            breakpoints: {
                1280: {
                    perPage: 4.25,
                    gap: '0.65rem',
                },
                1024: {
                    perPage: 3.25,
                    perMove: 1,
                    gap: '0.55rem',
                },
                768: {
                    perPage: 2,
                    perMove: 1,
                    gap: '0.3rem',
                    padding: { right: '1.25rem' }
                },
                640: {
                    perPage: 2,
                    perMove: 1,
                    gap: '0.25rem',
                    padding: { right: '0.875rem' }
                },
                480: {
                    perPage: 2,
                    perMove: 1,
                    gap: '0.2rem',
                    padding: { right: '0.75rem' }
                },
            }
        }
    }

    updateProgress() {
        if (!this.splide || !this.hasProgressBarTarget) {
            return;
        }

        const { Move } = this.splide.Components;
        const start = Move.getLimit(false);
        const end = Move.getLimit(true);
        const position = Move.getPosition();
        const ratio = start === end ? 1 : (position - start) / (end - start);
        const progress = Math.min(Math.max(ratio, 0), 1);

        this.progressBarTarget.style.transform = `scaleX(${progress})`;

        if (this.hasProgressTarget) {
            this.progressTarget.setAttribute('aria-valuemin', '0');
            this.progressTarget.setAttribute('aria-valuemax', '100');
            this.progressTarget.setAttribute('aria-valuenow', `${Math.round(progress * 100)}`);
        }
    }

    updateProgressForIndex(index) {
        if (!this.splide || !this.hasProgressBarTarget) {
            return;
        }

        const endIndex = this.splide.Components.Controller.getEnd();
        const safeIndex = Math.max(0, Math.min(index, endIndex));
        const progress = endIndex <= 0 ? 1 : safeIndex / endIndex;

        this.progressBarTarget.style.transform = `scaleX(${progress})`;

        if (this.hasProgressTarget) {
            this.progressTarget.setAttribute('aria-valuemin', '0');
            this.progressTarget.setAttribute('aria-valuemax', '100');
            this.progressTarget.setAttribute('aria-valuenow', `${Math.round(progress * 100)}`);
        }
    }

    prev() {
        if (!this.splide) {
            return;
        }

        this.splide.go('<');
    }

    next() {
        if (!this.splide) {
            return;
        }

        this.splide.go('>');
    }

    get timelineOptions() {
        return {
            easing: 'cubic-bezier(.18,.48,.3,.97)',
            speed: 1000,
            pagination: false,
            perPage: 5,
            perMove: 5,
            padding: { left: 20, right: 20 },
            breakpoints: {
                1024: {
                    perPage: 3,
                    perMove: 3,
                    padding: { left: 20, right: 60 },
                },
                767: {
                    direction: 'ttb',
                    perPage: 9,
                    arrows: false,
                    drag: false,
                    gap: '2.5rem',
                    height: 'auto',
                    padding: { top: '3rem' }
                },
                640: {
                    direction: 'ttb',
                    perPage: 9,
                    arrows: false,
                    drag: false,
                    gap: '2.5rem',
                    padding: { top: '3rem' }
                }
            }
        }
    }

    get shopInfoOptions() {
        const options = {
            type: 'slide',
            easing: 'cubic-bezier(.22,1,.36,1)',
            speed: 560,
            pagination: false,
            arrows: false,
            drag: true,
            snap: true,
            focus: 0,
            trimSpace: true,
            omitEnd: false,
            waitForTransition: false,
            updateOnMove: true,
            flickPower: 80,
            flickMaxPages: 1,
            perPage: 3.15,
            perMove: 1,
            gap: '1rem',
            breakpoints: {
                1024: {
                    autoWidth: true,
                    focus: 'center',
                    trimSpace: true,
                    omitEnd: false,
                    gap: '0.85rem',
                },
                768: {
                    autoWidth: true,
                    focus: 'center',
                    trimSpace: true,
                    omitEnd: false,
                    gap: '0.55rem',
                },
                640: {
                    autoWidth: true,
                    focus: 'center',
                    trimSpace: true,
                    omitEnd: false,
                    gap: '0.45rem',
                },
                480: {
                    autoWidth: true,
                    focus: 'center',
                    trimSpace: true,
                    omitEnd: false,
                    gap: '0.35rem',
                },
            }
        };

        if (!this.peekValue) {
            return options;
        }

        options.padding = { right: '0.85rem' };
        options.breakpoints[1024].padding = { right: '1.6rem' };
        options.breakpoints[768].padding = { right: '1.45rem' };
        options.breakpoints[640].padding = { right: '1.25rem' };
        options.breakpoints[480].padding = { right: '1.1rem' };

        return options;
    }

    get defaultOptions() {
        return {}
    }
}
