/*
* A widget to make a custom scrollable area.
*
* @author Hao Tan
*
*/

YAHOO.namespace("SW.widget.Scroller");

(function(){
    var yuiDom = YAHOO.util.Dom;

    var DEFAULT_CONFIG = {
        viewPortElement:null, // NOTE: this must be supplied
        scrollingElement:null, // NOTE: this must be supplied
        scrollHeight: 0,
        upScrollStep: 25,
        downScrollStep: 25,
        autoScrollInterval: 0.850,
        upDuration: 0.950,
        downDuration: 0.950,
        upTransition:YAHOO.util.Easing.easeNone,
        downTransition:YAHOO.util.Easing.easeNone
    };

    /*
    * @contstructor
    * @param {object} provides configuration for the widget see above 'DEFAULT_CONFIG'
    * @return An object that has a few methods to control the scrollable element
    */
    function Scroller (config) {
        if(!config.viewPortElement){
            throw("no element supplied to Scroller");
        }
        if(!config.scrollingElement){
            throw("no element supplied to Scroller");
        }

        for(var prop in DEFAULT_CONFIG) {
            if(!config.hasOwnProperty(prop)){
                config[prop] = DEFAULT_CONFIG[prop];
            }
        }

        var currentScrollValue = 0;
        var isScrolling = false;
        var scrollUpInterval = null;
        var scrollDownInterval = null;

        //  get scrollHeight from config or try to calculate a rough estimate of what it is
        config.scrollHeight = config.scrollHeight || (parseInt(yuiDom.getStyle(config.scrollingElement, "height"), 10) - parseInt(yuiDom.getStyle(config.viewPortElement, "height"), 10));

        if(config.autoScrollInterval) {
            config.autoScrollInterval *= 1000;
        }

        function scrollUpStep () {
            if(isScrolling) {
                if(currentScrollValue <= 0 ){
                    currentScrollValue = 0;
                    isScrolling = false;
                    return;
                }

                var scrollValue = currentScrollValue - config.upScrollStep;
                currentScrollValue = currentScrollValue - config.upScrollStep;

                var animateUp = new YAHOO.util.Scroll(config.viewPortElement, {scroll: {to: [0, scrollValue]}}, config.upDuration, config.upTransition);
                animateUp.animate();
            }
        }

        function scrollDownStep () {
            if(isScrolling) {
                if(currentScrollValue >= config.scrollHeight) {
                    currentScrollValue = config.scrollHeight;
                    isScrolling = false;
                    return;
                }
                var scrollValue = currentScrollValue + config.downScrollStep;
                currentScrollValue = currentScrollValue + config.downScrollStep;

                var animateDown = new YAHOO.util.Scroll(config.viewPortElement, {scroll: {to: [0, scrollValue]}}, config.downDuration, config.downTransition);
                animateDown.animate();
            }
        }

        var self = {
            stopScroll: function () {
                isScrolling = false;
                clearInterval(scrollUpInterval);
                scrollUpInterval = null;
                clearInterval(scrollDownInterval);
                scrollDownInterval = null;
            },
            scrollUp: function() {
                isScrolling = true;
                scrollUpStep();
            },
            autoScrollUp: function() {
                isScrolling = true;
                scrollUpInterval = setInterval(scrollUpStep, config.autoScrollInterval);
                scrollUpStep();
            },
            scrollDown: function() {
                isScrolling = true;
                scrollDownStep();
            },
            autoScrollDown: function() {
                isScrolling = true;
                scrollDownInterval = setInterval(scrollDownStep, config.autoScrollInterval);
                scrollDownStep();
            }
        };

        return self;
    }

    SW.widget.Scroller = function (config) {
        return new Scroller(config);
    };
})();
