

var Scroller = function() {
    return this.initialize.apply(this, arguments);
}

Scroller.prototype = {
    defaults: {
        speed : 12,
        wheelSpeed : 24,
        buttonEvent : 'mousedown',
        nextButtonHTML: '<a>READ ON</a>',
        prevButtonHTML: '<a>BACK</a>',
        paginate : false,
        resize: function(){ // resize callback for custom logic (can be overridden)
            var self = this;
            var $container = $(self.container).css('height','');
            var line_height = parseInt($container.css('line-height'));
            var h = $container.parent().height();
            $container.siblings().each(function(i,s){
                if( $(s).css('position') == 'absolute' ) return;
                var sh =  $(s).height() + parseInt($(s).css('marginTop')) + parseInt($(s).css('marginBottom'));
                h = h - sh;
            });
            h = Math.round(h / line_height) * line_height;
            $container.height(h - line_height);
            self.reset();
        },
        preInit: function(){ // called before initlize method (can be overridden)
            var self = this;
            var $container = $(self.container);
            $('p:last',$container).css('marginBottom','0px');
            var line_height = parseInt($container.css('line-height'));
            var h = $container.parent().height();
            $container.siblings().each(function(i,s){
                if( $(s).css('position') == 'absolute' ) return;
                var sh =  $(s).height() + parseInt($(s).css('marginTop')) + parseInt($(s).css('marginBottom'));
                h = h - sh;
            });
            h = Math.round(h / line_height) * line_height;
            $container.height(h - line_height);
        },
        postInit: null
    },

    timeoutID: 0,
    scrollCursor: 0,
    
    
    initialize: function (obj, settings) {
        var self = this;
        self.settings = jQuery.extend({}, self.defaults, settings);
        self.container = obj;
        var $container = $(self.container);

        // Set up Callbacks
        self.resize = self.settings.resize;
        self.preInit = self.settings.preInit;
        self.postInit = self.settings.postInit;
        if(self.settings.preInit) self.preInit();
        

        $container.css({
            overflow: 'hidden'
        }).addClass('jquery-scroller');


        // Buttons  (hacks prevail.  clean this up for other sites )
        $('.scroller-prev, .scroller-next', $container.parent().parent()).remove();
        self.prevButton = $(self.settings.prevButtonHTML).
            addClass('scroller-prev').hide().appendTo( $container.parent().parent() )[0];
        self.nextButton = $(self.settings.nextButtonHTML).
            addClass('scroller-next').appendTo( $container.parent().parent() )[0];
        
        // Events
        if( self.settings.paginate ) {
            var line_height = parseInt($container.css('line-height'));
            $(self.nextButton).click(function() {
                self.settings.speed = $(self.container).height() - (line_height*2);
                self.update(self.settings.speed);
            });
            $(self.prevButton).click(function() {
                self.settings.speed = $(self.container).height() - (line_height*2);
                self.update(0 - self.settings.speed);
            });
        } else {
            $container.mousewheel( function(e, delta){ self.wheel(e, delta); return false; } );
            $(self.nextButton).bind('mousedown', function(e){self.scrollNext()}).
                bind('mouseup', function(e){self.stopScroll(e)});
            $(self.prevButton).bind('mousedown', function(e){self.scrollPrev()}).
                bind('mouseup', function(e){self.stopScroll(e)});
        }
        
        // Custom Events
        $container.bind('scrollbegining', function(){
            if(self.settings.paginate) {
                self.stopScroll();
                $(self.prevButton).hide();
            }
        });
        $container.bind('scrollend', function(){
            if(self.settings.paginate) {
                self.stopScroll();
                $(self.nextButton).hide();
            }
        });

        self.reset();
        self.resize();
        $(window).load(function(){self.resize()});

        if(self.postInit) self.postInit();
    },

    reset: function() {
        var self = this;
        self.scrollCursor = self.container.scrollTop = 0;
        if( self.scrollNeeded() ) {
            $(self.nextButton).show();
        } else {
            $(self.nextButton).hide();
        }
        $(self.prevButton).hide();
    },

    update: function(s){
        var self = this;
        self.scrollCursor = self.scrollCursor + s;
        if( self.scrollCursor <= 0 ){
            self.scrollCursor = 0;
            $(self.container).trigger('scrollbegining');
        } else { $(self.prevButton).show(); }

        if( self.scrollCursor >= (self.container.scrollHeight - $(self.container).height() ) ) {
            $(self.container).trigger('scrollend');
        } else { $(self.nextButton).show(); }
        
        if( self.settings.paginate ) {
            $(self.container).animate({
                scrollTop: self.scrollCursor
            });
        } else {
            self.container.scrollTop = self.scrollCursor;
            self.scrollCursor = self.container.scrollTop; // browser keeps upper bounds on scrollTop
        }
    },

    stopScroll: function() {
        var self = this;
        clearTimeout(self.timeoutID);
    },

    scrollPrev: function() {
        var self = this;
        self.update(0 - self.settings.speed);        
        self.timeoutID = setTimeout(function(){self.scrollPrev();}, 60);        
    },

    scrollNext: function() {
        var self = this;
        self.update(self.settings.speed);
        self.timeoutID = setTimeout(function(){self.scrollNext();}, 60);
    },

    wheel: function(event, delta) {
        var self = this;
        if($.browser.opera) delta = delta * -1; // delta sign oppisite in opera
        direction = (delta < 0)? 1 : -1;
        self.update(self.settings.wheelSpeed * direction);
        return false;
    },

    scrollNeeded: function() {
        var self = this;
        if( self.container.scrollHeight > $(self.container).height() ) return true;        
        return false;
    }
        
};


jQuery.fn.Scroller = function(settings) {
    return this.each( function (i,el) {
        if( el.jqueryScroller) {
            el.jqueryScroller.preInit();
            el.jqueryScroller.reset();            
        } else {
            el.jqueryScroller =  new Scroller(el, settings);
        }
    });
}
