/**
 * Goweb Scroller
 * 
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2010 (c) Goweb (http://www.goweb.pt)
 * 
 */

if(typeof(Prototype) == "undefined") {
    throw "Goweb.Scroller requires Prototype to be loaded."; }

if(typeof(Control.Slider) == "undefined")
    throw "Goweb.Scroller requires Control.Slider to be loaded.";

if(typeof(Event.wheel) == "undefined") {
	Object.extend(Event, {
			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;     
			}
			return Math.round(delta); //Safari Round
		}
	});
}

if(typeof(Goweb) == "undefined") {
	var Goweb = Class.create();
}

Goweb.Scroller = Class.create({
	initialize: function(name, options) {
		this.name = name;
		this.initialized = false;
		this.mainContainer = $(this.name + '_scrollable');
		this.trackContainer = $(this.name + '_track');
		this.handleContainer = $(this.name + '_handle');
		if (!this.mainContainer){
			throw "Goweb.Scroller requires '" + this.name + "_scrollable' to be defined";
		}
		if (!this.trackContainer){
			throw "Goweb.Scroller requires '" + this.name + "_track' to be defined";
		}
		if (!this.handleContainer){
			throw "Goweb.Scroller requires '" + this.name + "_handle' to be defined";
		}
		this.slider = false;
		this.interval = false;
		this.options = {
                type: 'vertical', //tipo de scroll, vertical ou horizontal
                scrollValue: 0.1, // fazer scroll em 10% do total, em cada click ou scroll da roda do rato
                width: '20px', // largura do elemento
                height: '20px', // altura do elemento
                startReverse: 0, // começar no final (fundo ou direita)
                click: 0, // adicionar eventos para click em vez de mouseover e mouseout
                wheel: 1, // adicionar eventos para a roda do rato
                hideScroller: 0, // esconder o scroller, se o conteúdo não for suficiente
                slider_options: {} // opções para o slider, ver em http://wiki.github.com/madrobby/scriptaculous/slider
		};
		Object.extend(this.options, options || {});
        this.slider = new Control.Slider(this.handleContainer,this.trackContainer,Object.extend({
            axis: this.options.type,
            onSlide: this.onChange.bind(this),
            onChange: this.onChange.bind(this)
        },this.options.slider_options));
        if (this.options.startReverse){
        	this.slider.setValue(1);
        }

    	if (this.mainContainer.style.overflow != "hidden"){
    		this.mainContainer.style.overflow = "hidden";
    		if (Prototype.Browser.IE) {
    			this.mainContainer.style.position = "relative";
    		}
    	}

    	if (!this.mainContainer.style.width){
    		this.mainContainer.style.width = this.options.width;
    	}

    	if (!this.mainContainer.style.height){
    		this.mainContainer.style.height = this.options.height;
    	}
    	if ($(this.name + '_buttonLess')){
    		if (this.options.click){
    			$(this.name + '_buttonLess').observe('click', this.scrollLess.bind(this));
    		} else {
    			$(this.name + '_buttonLess').observe('mouseover', function() { this.interval = setInterval(this.scrollLess.bind(this), 100); return false; });
    			$(this.name + '_buttonLess').observe('mouseout', function() { clearInterval(this.interval); return false; });
    		}
    	}
    	if ($(this.name + '_buttonMore')){
    		if (this.options.click){
    			$(this.name + '_buttonMore').observe('click', this.scrollMore.bind(this));
    		} else {
    			$(this.name + '_buttonMore').observe('mouseover', function() { this.interval = setInterval(this.scrollMore.bind(this), 100); return false; });
    			$(this.name + '_buttonMore').observe('mouseout', function() { clearInterval(this.interval); return false; });
    		}
    	}
        this.initialized = true;
        if (this.options.wheel){
			this.mainContainer.observe('DOMMouseScroll',this.onMouseWheel.bind(this));
			this.mainContainer.observe('mousewheel',this.onMouseWheel.bind(this));
        }
		if (this.options.type == 'vertical'){
			// if content doesn't need scroll remove it
	    	if (this.options.hideScroller && this.mainContainer.scrollHeight <= this.mainContainer.offsetHeight) {
	    		this.slider.setDisabled();
	    		this.trackContainer.hide();
	    	}
		} else {
	    	if (this.mainContainer.style.whiteSpace != 'nowrap'){
	    		this.mainContainer.style.whiteSpace = 'nowrap';
	    	}
		}
	},
    onChange: function(value){
		if (this.options.type == 'vertical'){
			this.mainContainer.scrollTop = Math.round(value/this.slider.maximum*(this.mainContainer.scrollHeight-this.mainContainer.offsetHeight));
		} else {
			this.mainContainer.scrollLeft = Math.round(value/this.slider.maximum*(this.mainContainer.scrollWidth-this.mainContainer.offsetWidth));
		}
    },
	scrollMore: function(){
		this.slider.setValue(this.slider.value+this.options.scrollValue);
	},
	scrollLess: function(){
		this.slider.setValue(this.slider.value-this.options.scrollValue);
	},
	onMouseWheel: function(event){
		var delta = Event.wheel(event);
		if (delta) {
			if (delta < 0){
				this.scrollMore();
			} else {
				this.scrollLess();
			}
		}
        return false;
    }
});