
if(typeof(Prototype) == 'undefined' ||
    parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1]) < 1.5)
    throw(metaInfo.name + ' requires Prototype library >= 1.5.0.');

var Scroller = Class.create();
Scroller.prototype = {
    
    initialize: function (id) {
        /* Options */
        this.direction = 'vertical';
        this.speed = 10;        
        this.wheelSpeed = 30;
        this.upButton = 'scrollUp';
        this.downButton = 'scrollDown'; 
        this.fadeButtons = false;
        this.fadeBoundary = 120;
        this.scrollOnClick = true;
        this.scrollOnHover = false;
        this.widthOffset = 0; // Scroller will have width of window minus this amount
        this.wraparound = false;
        this.wrapHiddenClass = 'ScrollHidden';

        /* Private  */
        this.timeoutID = 0;
        this.container = null;
        this.wrapper = null
        this.scrollCursor = 0;
        this.scrollLength = 0;
        this.setWidth = 0;

        Object.extend(this, arguments[1] || {});

        var container = $(id);
        if (! container) return;
        this.container = container;
               
        var wrapper = container.cloneNode(true);
        wrapper.setAttribute('id', '');
        container.innerHTML = '';
        container.appendChild(wrapper);
        this.wrapper = wrapper;
        
        this.container.style.overflow = 'hidden';
        if( this.direction == 'horizontal' ) {
            wrapper.style.width = Element.getDimensions(wrapper)['width'] + 'px';
            this.scrollLength = this.container.scrollWidth;
            this.dimension = 'width';
        }
        else {
            this.scrollLength = Element.getHeight(wrapper);
            this.dimension = 'height';
        }

        this.setLength = this.container.scrollLength;
        if(this.wraparound == true ) {
            this.cloneContent();
        }
        
        if(this.widthOffset > 0){
            Event.observe(window, 'resize', this.resizeScroller.bind(this));
            this.resizeScroller();
        }
        
        Event.observe(container, 'DOMMouseScroll', this.wheel.bind(this));            
        Event.observe(container, 'mousewheel', this.wheel.bind(this));
        
        this.up_obj = $(this.upButton);
        this.dn_obj =  $(this.downButton);
        if( !this.up_obj ) {
            this.up_obj = document.createElement('img');
            this.up_obj.setAttribute('id',this.upButton);
            this.up_obj.src = '/img/up.png';
            Element.addClassName(this.up_obj, 'rollover');
            Element.addClassName(this.up_obj, 'transpng');
            Element.up(this.container).appendChild(this.up_obj);
        }
        if( !this.dn_obj ) {
            this.dn_obj = document.createElement('img');
            this.dn_obj.setAttribute('id',this.downButton);
            this.dn_obj.src = '/img/down.png';
            Element.addClassName(this.dn_obj, 'rollover');
            Element.addClassName(this.dn_obj, 'transpng');
            Element.up(this.container).appendChild(this.dn_obj);
        }
        this.checkScrollNeeded();
        if( this.fadeButtons == true )  {
            Element.hide(this.up_obj); Element.hide(this.dn_obj);
            Event.observe(document.body, 'mousemove', this.buttonFadeCheck.bindAsEventListener(this));
        }
        if( this.scrollOnHover == true ) {
            Event.observe(this.up_obj, 'mouseover', this.scrollUp.bind(this));
            Event.observe(this.up_obj, 'mouseout', this.stopScroll.bind(this));
            Event.observe(this.dn_obj, 'mouseover', this.scrollDown.bind(this));
            Event.observe(this.dn_obj, 'mouseout', this.stopScroll.bind(this));
        }
        else {
            Event.observe(this.up_obj, 'mousedown', this.scrollUp.bind(this));
            Event.observe(this.up_obj, 'mouseup', this.stopScroll.bind(this));
            Event.observe(this.dn_obj, 'mousedown', this.scrollDown.bind(this));
            Event.observe(this.dn_obj, 'mouseup', this.stopScroll.bind(this));
        }
        Event.observe(this.container, 'mouseout', this.stopScroll.bind(this));
                
    },

    update: function(){
        if( this.direction.toLowerCase() == 'vertical' ) {
            this.container.scrollTop = this.scrollCursor;            
        }
        else{
            this.container.scrollLeft = this.scrollCursor;
        }

    },

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

    moveUp: function(s) {
        var dim = Element.getDimensions(this.container);
        var scroll_end = this.scrollLength - dim[this.dimension];

        this.scrollCursor -= s;
        if( this.wraparound ==true ) {            
            if( this.scrollCursor <= 0 ) {
                this.scrollCursor = parseInt(this.setLength - s);
            }
        }
        else {            
            this.scrollCursor = (this.scrollCursor) < 0 ? 0 : this.scrollCursor;
        }
        this.update();
    },

    moveDown: function(s) {
        var dim = Element.getDimensions(this.container);
        var scroll_end = this.scrollLength - dim[this.dimension];
        
        this.scrollCursor += s;
        if( this.wraparound == true ) {            
            if( this.scrollCursor >= parseInt(this.setLength+s) ) {
                this.scrollCursor = 0;                
            }            
        }
        else {
            this.scrollCursor = (this.scrollCursor > scroll_end) ? scroll_end : this.scrollCursor;
        }
        this.update();
    },

    scrollUp: function() {
        this.moveUp(this.speed);
        var self = this;
        this.timeoutID = setTimeout(function(){self.scrollUp();}, 60);        
    },

    scrollDown: function() {
        this.moveDown(this.speed);
        var self = this;
        this.timeoutID = setTimeout(function(){self.scrollDown();}, 60);                    
    },

    resetScroll: function() {
        this.container.scrollTop = 0;
        this.scrollCursor = 0;        
    },

    resizeScroller: function() {
        w = getWindowWidth();
        size = w - this.widthOffset;
        this.container.style.width = size + 'px';
        this.checkScrollNeeded();
    },

    wheel: function(event){
        var delta = 0;
        if (!event) event = window.event;
        if (event.wheelDelta) {
            delta = event.wheelDelta/120; 
            if (window.opera) delta = -delta;
        } else if (event.detail) {
            delta = -event.detail/3;
        }
        if (delta)
            this.handleWheel(delta);
        if (event.preventDefault)
            event.preventDefault();
        event.returnValue = false;
    },

    handleWheel: function(delta) {
        if (delta < 0) { // down
            this.moveDown(this.wheelSpeed);            
        }
        else { //up            
            this.moveUp(this.wheelSpeed);
        }
    },

    buttonFadeCheck: function(e) {
        var x = Event.pointerX(e); var y = Event.pointerY(e);
        var up_obj = Element.down(this.up_obj);
        var dn_obj = Element.down(this.dn_obj);
        if(!Position.within(this.container, x,y)) {
            Element.hide(up_obj); Element.hide(dn_obj);
            return; 
        }
        var x = x - Position.page(this.container)[0] - Position.realOffset(this.container)[0];
        var width = Element.getWidth(this.container);
        if( x > width - this.fadeBoundary ) {                        
            if(! Element.visible(dn_obj))
                Element.show(dn_obj);
        }
        else Element.hide(dn_obj);
        
        if(  x < this.fadeBoundary ) {
            if(! Element.visible(up_obj))
                Element.show(up_obj);
        }
        else Element.hide(up_obj);
    },

    checkScrollNeeded: function() {
        
        if( this.wraparound == true) {
            var wrapcontent = document.getElementsByClassName(this.wrapHiddenClass);
            wrapcontent.each(Element.hide);
        }

        var scrolling = this.scrollNeeded();
        if( scrolling ) {
            Element.show(this.upButton);
            Element.show(this.downButton);
            if( wrapcontent) {
                wrapcontent.each(Element.show);                
            }
        }
        else {
            this.scrollCursor = 0; this.update();
            Element.hide(this.up_obj);
            Element.hide(this.dn_obj);
        }
    },

    scrollNeeded: function() {
        var dim = Element.getDimensions(this.container);
        if( this.scrollLength > dim[this.dimension]) 
            return true;

        return false;
    },

    cloneContent: function() {
        var children = Element.immediateDescendants(this.wrapper);
        children.each( function(child) {
            Element.setStyle({'float':'left'});
            var copy = child.cloneNode(true);
            Element.addClassName(copy, this.wrapHiddenClass);
            this.wrapper.appendChild(copy);
        }.bind(this));
        this.wrapper.style.width = parseInt(Element.getWidth(this.wrapper) * 2.5) + 'px';
    }
    
};


// Get width of window
function getWindowWidth() { 
    if (self.innerWidth) { 
        return self.innerWidth;         
    } 
    else if (document.documentElement && document.documentElement.clientWidth) { 
        return document.documentElement.clientWidth;         
    } 
    else if (document.body) { 
        return document.body.clientWidth;         
    } 
} 

document.observe('dom:loaded', function () {    
    var scroller = new Scroller('scroller');
});
