/**
 * SmoothScroll.js - v1.4.10
 * Licensed under the MIT license.
 * (Simplified for Webtaru Site Options)
 */
(function () {
    "use strict";

    var defaultOptions = {
        frameRate: 150,
        animationTime: 400,
        stepSize: 100,
        pulseAlgorithm: true,
        pulseScale: 4,
        pulseNormalize: 1,
        accelerationDelta: 50,
        accelerationMax: 3,
        keyboardSupport: true,
        arrowControls: 50,
        touchpadSupport: false,
        fixedBackground: true,
        excluded: ""
    };

    var options = defaultOptions;
    if (window.wtolsSmoothScroll) {
        options = Object.assign({}, defaultOptions, window.wtolsSmoothScroll);
    }

    var isExcluded = false;
    var isFrame = false;
    var direction = { x: 0, y: 0 };
    var initDone = false;
    var root = document.documentElement;
    var activeElement;
    var observer;
    var refreshSize;
    var deltaBuffer = [];
    var isMac = /^Mac/.test(navigator.platform);

    var key = {
        left: 37, up: 38, right: 39, down: 40, spacebar: 32,
        pageup: 33, pagedown: 34, end: 35, home: 36
    };

    function init() {
        if (initDone || !document.body) return;
        initDone = true;

        var body = document.body;
        var html = document.documentElement;
        var windowHeight = window.innerHeight;
        var scrollHeight = body.scrollHeight;

        root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
        activeElement = body;

        if (top != self) {
            isFrame = true;
        } else if (scrollHeight > windowHeight &&
            (body.offsetHeight <= windowHeight ||
                html.offsetHeight <= windowHeight)) {
            var fullPageElem = document.createElement("div");
            fullPageElem.style.cssText = "position:absolute; z-index:-10000; " +
                "top:0; left:0; right:0; height:" + root.scrollHeight + "px";
            document.body.appendChild(fullPageElem);
            var pendingRefresh;
            refreshSize = function () {
                if (pendingRefresh) return;
                pendingRefresh = setTimeout(function () {
                    if (isExcluded) return;
                    fullPageElem.style.height = '0';
                    fullPageElem.style.height = root.scrollHeight + 'px';
                    pendingRefresh = null;
                }, 500);
            };
            setTimeout(refreshSize, 10);
            addEvent("resize", refreshSize);
            var config = { attributes: true, childList: true, characterData: false };
            observer = new MutationObserver(refreshSize);
            observer.observe(body, config);
            if (root.offsetHeight <= windowHeight) {
                var header = document.createElement("div");
                header.style.clear = "both";
                body.prepend(header);
            }
        }

        if (!options.fixedBackground && !isExcluded) {
            body.style.backgroundAttachment = "scroll";
            html.style.backgroundAttachment = "scroll";
        }
    }

    var que = [];
    var pending = false;
    var lastScroll = Date.now();

    function scrollArray(elem, left, top) {
        tcp(top);
        if (options.accelerationMax > 0) {
            var now = Date.now();
            var elapsed = now - lastScroll;
            if (elapsed < options.accelerationDelta) {
                var factor = (1 + (50 / elapsed)) / 2;
                if (factor > 1) {
                    factor = Math.min(factor, options.accelerationMax);
                    left *= factor;
                    top *= factor;
                }
            }
            lastScroll = Date.now();
        }

        que.push({
            x: left,
            y: top,
            lastX: (left < 0) ? 0.99 : -0.99,
            lastY: (top < 0) ? 0.99 : -0.99,
            start: Date.now()
        });

        if (pending) return;

        var scrollWindow = (elem === document.body || elem === document.documentElement);
        if (scrollWindow && elem.style.scrollBehavior === 'smooth') return;

        var step = function (time) {
            var now = Date.now();
            var scrollX = 0;
            var scrollY = 0;

            for (var i = 0; i < que.length; i++) {
                var item = que[i];
                var elapsed = now - item.start;
                var finished = (elapsed >= options.animationTime);
                var position = (finished) ? 1 : elapsed / options.animationTime;

                if (options.pulseAlgorithm) {
                    position = pulse(position);
                }

                var x = (item.x * position - item.lastX) >> 0;
                var y = (item.y * position - item.lastY) >> 0;

                scrollX += x;
                scrollY += y;

                item.lastX += x;
                item.lastY += y;

                if (finished) {
                    que.splice(i, 1);
                    i--;
                }
            }

            if (scrollWindow) {
                window.scrollBy(scrollX, scrollY);
            } else {
                if (scrollX) elem.scrollLeft += scrollX;
                if (scrollY) elem.scrollTop += scrollY;
            }

            if (!left && !top) {
                que = [];
            }

            if (que.length) {
                requestAnimationFrame(step, elem);
            } else {
                pending = false;
            }
        };

        requestAnimationFrame(step, elem);
        pending = true;
    }

    function wheel(event) {
        if (!initDone) init();
        var target = event.target;
        var overflowing = overflowingAncestor(target);

        if (!overflowing || event.defaultPrevented || event.ctrlKey) return true;
        if (isNodeName(activeElement, "embed") || (isNodeName(target, "embed") && /\.pdf$/i.test(target.src)) || isNodeName(activeElement, "object")) return true;

        var deltaX = -event.wheelDeltaX || event.deltaX || 0;
        var deltaY = -event.wheelDeltaY || event.deltaY || 0;

        if (isMac) {
            if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) deltaX = -event.wheelDeltaX / 120 * options.stepSize;
            if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) deltaY = -event.wheelDeltaY / 120 * options.stepSize;
        }

        if (!deltaX && !deltaY) deltaY = -event.wheelDelta || 0;
        if (event.deltaMode === 1) {
            deltaX *= 40;
            deltaY *= 40;
        }

        if (Math.abs(deltaX) > 1.2) deltaX *= options.stepSize / 120;
        if (Math.abs(deltaY) > 1.2) deltaY *= options.stepSize / 120;

        scrollArray(overflowing, deltaX, deltaY);
        event.preventDefault();
        scheduleClearCache();
    }

    var cache = {};
    setInterval(function () { cache = {}; }, 10 * 1000);

    var uniqueID = (function () {
        var i = 0;
        return function (el) {
            return el.uniqueID || (el.uniqueID = i++);
        };
    })();

    function setCache(elems, overflowing) {
        for (var i = elems.length; i--;)
            cache[uniqueID(elems[i])] = overflowing;
        return overflowing;
    }

    function overflowingAncestor(el) {
        var elems = [];
        var body = document.body;
        var rootScrollHeight = root.scrollHeight;
        do {
            var cached = cache[uniqueID(el)];
            if (cached) return setCache(elems, cached);
            elems.push(el);
            if (rootScrollHeight <= root.clientHeight) {
                var isWindowScroll = (getComputedStyle(body, "").getPropertyValue("overflow-y") !== "hidden" &&
                    getComputedStyle(html, "").getPropertyValue("overflow-y") !== "hidden");
                if (isWindowScroll) return setCache(elems, getRootElement());
            }
            if (isScrollable(el)) return setCache(elems, el);
        } while (el = el.parentElement);
    }

    function isScrollable(el) {
        if (el.scrollHeight <= el.clientHeight) return false;
        var overflow = getComputedStyle(el, "").getPropertyValue("overflow-y");
        return (overflow === "scroll" || overflow === "auto");
    }

    function isNodeName(el, name) {
        return (el.nodeName || "").toLowerCase() === name.toLowerCase();
    }

    function getRootElement() {
        return (document.scrollingElement || root);
    }

    function addEvent(type, fn) {
        window.addEventListener(type, fn, { passive: false });
    }

    function isDivisible(n, d) {
        return (Math.floor(n / d) == n / d);
    }

    function pulse_(x) {
        var val, res;
        x = x * options.pulseScale;
        if (x < 1) {
            val = x - (1 - Math.exp(-x));
        } else {
            var start = Math.exp(-1);
            x -= 1;
            res = 1 - Math.exp(-x);
            val = start + (res * (1 - start));
        }
        return val * options.pulseNormalize;
    }

    function pulse(x) {
        if (x >= 1) return 1;
        if (x <= 0) return 0;
        if (options.pulseNormalize == 1) {
            options.pulseNormalize /= pulse_(1);
        }
        return pulse_(x);
    }

    var scheduleClearCache = (function() {
        var timer;
        return function() {
            clearTimeout(timer);
            timer = setTimeout(function() { cache = {}; }, 1000);
        };
    })();

    function tcp(top) {
        // Placeholder for potentially handling touchpad specific logic
    }

    if (window.addEventListener) {
        addEvent("wheel", wheel);
        addEvent("mousedown", function(e) { activeElement = e.target; });
        addEvent("load", init);
    }
})();
