jQuery(document).ready(function($){

// SmoothScroll v0.9.9
// Licensed under the terms of the MIT license.

// People involved
// - Balazs Galambosi: maintainer (CHANGELOG.txt)
// - Patrick Brunner (patrickb1991@gmail.com)
// - Michael Herf: ssc_pulse Algorithm

// Scroll Variables (tweakable)
    var ssc_framerate = 150; // [Hz]
    var ssc_animtime  = 500; // [px]
    var ssc_stepsize  = 150; // [px]

// ssc_pulse (less tweakable)
// ratio of "tail" to "acceleration"
    var ssc_pulseAlgorithm = true;
    var ssc_pulseScale     = 6;
    var ssc_pulseNormalize = 1;

// Keyboard Settings
    var ssc_keyboardsupport = true;
    var ssc_arrowscroll     = 50; // [px]

// Other Variables
    var ssc_frame = false;
    var ssc_direction = { x: 0, y: 0 };
    var ssc_initdone  = false;
    var ssc_fixedback = true;
    var ssc_root = document.documentElement;
    var ssc_activeElement;

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

    /***********************************************
     * INITIALIZE
     ***********************************************/

    /**
     * Sets up scrolls array, determines if ssc_frames are involved.
     */
    function ssc_init() {

        if (!document.body) return;

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

        // check compat mode for ssc_root element
        ssc_root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
        ssc_activeElement = body;

        ssc_initdone = true;

        // Checks if this script is running in a ssc_frame
        if (top != self) {
            ssc_frame = true;
        }

        /**
         * This fixes a bug where the areas left and right to
         * the content does not trigger the onmousewheel event
         * on some pages. e.g.: html, body { height: 100% }
         */
        else if (scrollHeight > windowHeight &&
            (body.offsetHeight <= windowHeight ||
                html.offsetHeight <= windowHeight)) {
            ssc_root.style.height = "auto";
            if (ssc_root.offsetHeight <= windowHeight) {
                var underlay = document.createElement("div");
                underlay.style.clear = "both";
                body.appendChild(underlay);
            }
        }

        if (!ssc_fixedback) {
            body.style.backgroundAttachment = "scroll";
            html.style.backgroundAttachment = "scroll";
        }

        if (ssc_keyboardsupport) {
            ssc_addEvent("keydown", ssc_keydown);
        }
    }


    /************************************************
     * SCROLLING
     ************************************************/

    var ssc_que = [];
    var ssc_pending = false;

    /**
     * Pushes scroll actions to the scrolling queue.
     */
    function ssc_scrollArray(elem, left, top, delay) {

        delay || (delay = 1000);
        ssc_directionCheck(left, top);

        // push a scroll command
        ssc_que.push({
            x: left,
            y: top,
            lastX: (left < 0) ? 0.99 : -0.99,
            lastY: (top  < 0) ? 0.99 : -0.99,
            start: +new Date
        });

        // don't act if there's a ssc_pending queue
        if (ssc_pending) {
            return;
        }

        var step = function() {

            var now = +new Date;
            var scrollX = 0;
            var scrollY = 0;

            for (var i = 0; i < ssc_que.length; i++) {

                var item = ssc_que[i];
                var elapsed  = now - item.start;
                var finished = (elapsed >= ssc_animtime);

                // scroll position: [0, 1]
                var position = (finished) ? 1 : elapsed / ssc_animtime;

                // easing [optional]
                if (ssc_pulseAlgorithm) {
                    position = ssc_pulse(position);
                }

                // only need the difference
                var x = (item.x * position - item.lastX) >> 0;
                var y = (item.y * position - item.lastY) >> 0;

                // add this to the total scrolling
                scrollX += x;
                scrollY += y;

                // update last values
                item.lastX += x;
                item.lastY += y;

                // delete and step back if it's over
                if (finished) {
                    ssc_que.splice(i, 1); i--;
                }
            }

            // scroll left
            if (left) {
                var lastLeft = elem.scrollLeft;
                elem.scrollLeft += scrollX;

                // scroll left failed (edge)
                if (scrollX && elem.scrollLeft === lastLeft) {
                    left = 0;
                }
            }

            // scroll top
            if (top) {
                var lastTop = elem.scrollTop;
                elem.scrollTop += scrollY;

                // scroll top failed (edge)
                if (scrollY && elem.scrollTop === lastTop) {
                    top = 0;
                }
            }

            // clean up if there's nothing left to do
            if (!left && !top) {
                ssc_que = [];
            }

            if (ssc_que.length) {
                setTimeout(step, delay / ssc_framerate + 1);
            } else {
                ssc_pending = false;
            }
        }

        // start a new queue of actions
        setTimeout(step, 0);
        ssc_pending = true;
    }


    /***********************************************
     * EVENTS
     ***********************************************/

    /**
     * Mouse ssc_wheel handler.
     * @param {Object} event
     */
    function ssc_wheel(event) {

        if (!ssc_initdone) {
            init();
        }

        var target = event.target;
        var overflowing = ssc_overflowingAncestor(target);

        // use default if there's no overflowing
        // element or default action is prevented
        if (!overflowing || event.defaultPrevented ||
            ssc_isNodeName(ssc_activeElement, "embed") ||
            (ssc_isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
            return true;
        }

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

        // use wheelDelta if deltaX/Y is not available
        if (!deltaX && !deltaY) {
            deltaY = event.wheelDelta || 0;
        }

        // scale by step size
        // delta is 120 most of the time
        // synaptics seems to send 1 sometimes
        if (Math.abs(deltaX) > 1.2) {
            deltaX *= ssc_stepsize / 120;
        }
        if (Math.abs(deltaY) > 1.2) {
            deltaY *= ssc_stepsize / 120;
        }

        ssc_scrollArray(overflowing, -deltaX, -deltaY);
        event.preventDefault();
    }

    /**
     * ssc_keydown event handler.
     * @param {Object} event
     */
    function ssc_keydown(event) {

        var target   = event.target;
        var modifier = event.ctrlKey || event.altKey || event.metaKey;

        // do nothing if user is editing text
        // or using a modifier ssc_key (except shift)
        if ( /input|textarea|embed/i.test(target.nodeName) ||
            target.isContentEditable ||
            event.defaultPrevented   ||
            modifier ) {
            return true;
        }
        // spacebar should trigger button press
        if (ssc_isNodeName(target, "button") &&
            event.keyCode === ssc_key.spacebar) {
            return true;
        }

        var shift, x = 0, y = 0;
        var elem = ssc_overflowingAncestor(ssc_activeElement);
        var clientHeight = elem.clientHeight;

        if (elem == document.body) {
            clientHeight = window.innerHeight;
        }

        switch (event.keyCode) {
            case ssc_key.up:
                y = -ssc_arrowscroll;
                break;
            case ssc_key.down:
                y = ssc_arrowscroll;
                break;
            case ssc_key.spacebar: // (+ shift)
                shift = event.shiftKey ? 1 : -1;
                y = -shift * clientHeight * 0.9;
                break;
            case ssc_key.pageup:
                y = -clientHeight * 0.9;
                break;
            case ssc_key.pagedown:
                y = clientHeight * 0.9;
                break;
            case ssc_key.home:
                y = -elem.scrollTop;
                break;
            case ssc_key.end:
                var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
                y = (damt > 0) ? damt+10 : 0;
                break;
            case ssc_key.left:
                x = -ssc_arrowscroll;
                break;
            case ssc_key.right:
                x = ssc_arrowscroll;
                break;
            default:
                return true; // a ssc_key we don't care about
        }

        ssc_scrollArray(elem, x, y);
        event.preventDefault();
    }

    /**
     * ssc_mousedown event only for updating ssc_activeElement
     */
    function ssc_mousedown(event) {
        ssc_activeElement = event.target;
    }


    /***********************************************
     * OVERFLOW
     ***********************************************/

    var ssc_cache = {}; // cleared out every once in while
    setInterval(function(){ ssc_cache = {}; }, 10 * 1000);

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

    function ssc_setCache(elems, overflowing) {
        for (var i = elems.length; i--;)
            ssc_cache[ssc_uniqueID(elems[i])] = overflowing;
        return overflowing;
    }

    function ssc_overflowingAncestor(el) {
        var elems = [];
        var ssc_rootScrollHeight = ssc_root.scrollHeight;
        do {
            var cached = ssc_cache[ssc_uniqueID(el)];
            if (cached) {
                return ssc_setCache(elems, cached);
            }
            elems.push(el);
            if (ssc_rootScrollHeight === el.scrollHeight) {
                if (!ssc_frame || ssc_root.clientHeight + 10 < ssc_rootScrollHeight) {
                    return ssc_setCache(elems, document.body); // scrolling ssc_root in WebKit
                }
            } else if (el.clientHeight + 10 < el.scrollHeight) {
                overflow = getComputedStyle(el, "").getPropertyValue("overflow");
                if (overflow === "scroll" || overflow === "auto") {
                    return ssc_setCache(elems, el);
                }
            }
        } while (el = el.parentNode);
    }


    /***********************************************
     * HELPERS
     ***********************************************/

    function ssc_addEvent(type, fn, bubble) {
        window.addEventListener(type, fn, (bubble||false));
    }

    function ssc_removeEvent(type, fn, bubble) {
        window.removeEventListener(type, fn, (bubble||false));
    }

    function ssc_isNodeName(el, tag) {
        return el.nodeName.toLowerCase() === tag.toLowerCase();
    }

    function ssc_directionCheck(x, y) {
        x = (x > 0) ? 1 : -1;
        y = (y > 0) ? 1 : -1;
        if (ssc_direction.x !== x || ssc_direction.y !== y) {
            ssc_direction.x = x;
            ssc_direction.y = y;
            ssc_que = [];
        }
    }


    /***********************************************
     * ssc_pulse
     ***********************************************/

    /**
     * Viscous fluid with a ssc_pulse for part and decay for the rest.
     * - Applies a fixed force over an interval (a damped acceleration), and
     * - Lets the exponential bleed away the velocity over a longer interval
     * - Michael Herf, http://stereopsis.com/stopping/
     */
    function ssc_pulse_(x) {
        var val, start, expx;
        // test
        x = x * ssc_pulseScale;
        if (x < 1) { // acceleartion
            val = x - (1 - Math.exp(-x));
        } else {     // tail
            // the previous animation ended here:
            start = Math.exp(-1);
            // simple viscous drag
            x -= 1;
            expx = 1 - Math.exp(-x);
            val = start + (expx * (1 - start));
        }
        return val * ssc_pulseNormalize;
    }

    function ssc_pulse(x) {
        if (x >= 1) return 1;
        if (x <= 0) return 0;

        if (ssc_pulseNormalize == 1) {
            ssc_pulseNormalize /= ssc_pulse_(1);
        }
        return ssc_pulse_(x);
    }

    $.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
    if ( $.browser.chrome ) {
        ssc_addEvent("mousedown", ssc_mousedown);
        ssc_addEvent("mousewheel", ssc_wheel);
        ssc_addEvent("load", ssc_init);
    }
});