/**
 * Animate scroll
 * Thanks to Dalton Walsch https://daltonwalsh.com/blog/using-the-intersection-observer/
 */

function initAnimateScroll()
{
    const visibleWithoutAnimationClass = 'quiqqer-animate-scroll-visible';
    const scrollElements = new Set(Array.from(document.querySelectorAll('.js-scroll')));
    const selectorConfig = typeof QUI_ANIMATE_SCROLL_EFFECTS === 'object'
        ? QUI_ANIMATE_SCROLL_EFFECTS
        : {};

    addElementsFromSettings(selectorConfig);

    let allElements = Array.from(scrollElements);

    if (!allElements.length) {
        return;
    }

    if (typeof IntersectionObserver !== 'function') {
        allElements.forEach(function(Elm) {
            showWithoutAnimation(Elm);
        });

        return;
    }

    if (
        typeof QUI_ANIMATE_SKIP_ANIMATION_IF_VISIBLE !== 'undefined'
        && QUI_ANIMATE_SKIP_ANIMATION_IF_VISIBLE === 1
    ) {
        allElements = allElements.filter(function(Elm) {
            if (!isInViewport(Elm)) {
                return true;
            }

            showWithoutAnimation(Elm);
            return false;
        });
    }

    if (!allElements.length) {
        return;
    }

    let threshold = 0.15;

    if (window.innerHeight < 500) {
        threshold = 0;
    }

    const options = {
        root: null, // relative to document viewport
        rootMargin: '0px', // margin around root. Values are similar to css property. Unit less values not allowed
        threshold: threshold // visible amount of item shown in relation to root
    };

    const observerCallback = function(entries) {
        entries.forEach((entry) => {
            if (entry.isIntersecting) {
                entry.target.classList.add('scrolled');
                observer.unobserve(entry.target);
            }
        });
    };

    const observer = new IntersectionObserver(observerCallback, options);

    allElements.forEach((Elm) => {
        observer.observe(Elm);
    });

    function addElementsFromSettings(SelectorObj)
    {
        if (!SelectorObj || Array.isArray(SelectorObj)) {
            return;
        }

        const effectClasses = {
            fadeIn: 'fade-in',
            bottom: 'fade-in-from-bottom',
            left: 'fade-in-from-left',
            right: 'fade-in-from-right'
        };

        Object.keys(effectClasses).forEach(function(effect) {
            if (typeof SelectorObj[effect] !== 'string') {
                return;
            }

            splitSelectorList(SelectorObj[effect]).forEach(function(selector) {
                let selectedElements;

                try {
                    selectedElements = document.querySelectorAll(selector);
                } catch (error) {
                    return;
                }

                selectedElements.forEach(function(Elm) {
                    Elm.classList.add('js-scroll');
                    Elm.classList.add(effectClasses[effect]);
                    scrollElements.add(Elm);
                });
            });
        });
    }

    function splitSelectorList(selectorList)
    {
        const selectors = [];
        let start = 0;
        let quote = '';
        let escaped = false;
        let bracketDepth = 0;
        let parenthesisDepth = 0;

        for (let index = 0; index < selectorList.length; index++) {
            const character = selectorList[index];

            if (escaped) {
                escaped = false;
                continue;
            }

            if (character === '\\') {
                escaped = true;
                continue;
            }

            if (quote) {
                if (character === quote) {
                    quote = '';
                }

                continue;
            }

            if (character === '"' || character === '\'') {
                quote = character;
                continue;
            }

            if (character === '[') {
                bracketDepth++;
                continue;
            }

            if (character === ']') {
                bracketDepth = Math.max(0, bracketDepth - 1);
                continue;
            }

            if (character === '(') {
                parenthesisDepth++;
                continue;
            }

            if (character === ')') {
                parenthesisDepth = Math.max(0, parenthesisDepth - 1);
                continue;
            }

            if (character === ',' && bracketDepth === 0 && parenthesisDepth === 0) {
                addSelector(selectorList.slice(start, index));
                start = index + 1;
            }
        }

        addSelector(selectorList.slice(start));
        return selectors;

        function addSelector(selector)
        {
            selector = selector.trim();

            if (selector) {
                selectors.push(selector);
            }
        }
    }

    function showWithoutAnimation(Elm)
    {
        Elm.classList.add(visibleWithoutAnimationClass);
        Elm.classList.remove('js-scroll');
    }

    // Helper function: Checks if an element is in the viewport
    function isInViewport(el)
    {
        const rect = el.getBoundingClientRect();
        return (
            rect.top < window.innerHeight &&
            rect.bottom > 0
        );
    }
}

if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initAnimateScroll);
} else {
    initAnimateScroll();
}
