//add element methods
Element.addMethods({
	
	scrollbar: function(element,para,onset){
		element = $(element);
		Df.Namespace.create('df',element).scrollbar = new Df.Scrollbar(element).set(para);
		return element;
	}
});

/*
 ref:	Df.Scrollbar
*/
Df.Scrollbar = Class.create(Df.Ui, {
	initialize: function($super, element){
		$super(element)
		
		this.setPars({
			scroll: {},
			classNames: {
				y: {
					holder: 'yHolder',
					prev: 'ArrowUp',
					next: 'ArrowDown',
					area: 'SlideArea',
					marker: 'marker'
				},
				x: {
					holder: 'xHolder',
					prev: 'ArrowLeft',
					next: 'ArrowRight',
					area: 'SlideArea',
					marker: 'marker'
				}
			},
			clickPercent:10,
			clickPixel:false,
			clickPause: 500,
			clickRepeat: 25
		});
		
		/** @private */
		this.yDrag;
		/** @private */
		this.xDrag;
		/** @private */
		this.yClickMove;
		/** @private */
		this.xClickMove;
		/** @private */
		this.maxY;
		/** @private */
		this.maxX;
		/** @private */
		this.yClickStatusNext = false;
		/** @private */
		this.yClickStatusPrev = false;
		/** @private */
		this.xClickStatusNext = false;
		/** @private */
		this.xClickStatusPrev = false;
		/** @private */
		this.eles = {
			y: {},
			x: {}
		}
		/** @private */
		this.dems = {
			holder:{},
			content:{},
			offset:{},
			x: {
				holder: {},
				prev: {},
				next: {},
				area: {},
				marker: {}
			},
			y: {
				holder: {},
				prev: {},
				next: {},
				area: {},
				marker: {}
			}
		}
		/** @private */
		this.yDragging = false;
		/** @private */
		this.xDragging = false;
		
		this._wheelControl = this.wheelControl.bind(this)
		
		return this
	},
	
	set: function($super, pars){
		$super(pars)
		
		this.element.scrollTop = 0;
		this.element.scrollLeft = 0
		
		this.adjustToContent()
		
		this.getElement().observe(':resize', this.adjustToContent.bind(this))
		
		Event.observe(document.body, 'mouseup', function(e){
				Event.stop(e)
				this.yClickStatusNext = false;
				this.xClickStatusNext = false;
				this.yClickStatusPrev = false;
				this.xClickStatusPrev = false;
		}.bind(this));
		
		return this
	},
	
	/*
	 ref:		Df.Scrollbar.getElements
	 type:		Method
	 returns:	{
				y: {
					holder,
					prev,
					area,
					marker,
					next
				},
				x: {
					holder,
					prev,
					area,
					marker,
					next
				}
			}
	*/
	getElements: function(){
		return this.eles;
	},
	
	adjustToContent: function(e){
		this.setDems();
		this.setPositions();
		
		this.element.stopObserving(':mousewheel', this._wheelControl);
		
		if (this.dems.content.height > this.dems.holder.height) {
			this.buildYBar();
			this.element.observe(':mousewheel', this._wheelControl);
			this.sizeDemsY();
			this.setIterationY();
			try{
				this.scrollY(parseInt(this.eles.y.marker.getStyle('top')))
			}catch(e){
				
			}
			
		}
		else if(this.eles.y.holder) {
			this.eles.y.holder.remove()
			this.eles.y = {}
		}
		
		if (this.dems.content.width > this.dems.holder.width) {
			this.buildXBar();
			this.sizeDemsX();
			this.setIterationX();
			try{
				this.scrollX(parseInt(this.eles.y.marker.getStyle('left')))
			}catch(e){
				
			}
		}
		else if(this.eles.x.holder) {
			this.eles.x.holder.remove()
			this.eles.x = {}
		}
	},
	
	setIterationY: function(){
		
		if (this.pars.clickPixel) {
			this.yClickMove = Math.ceil((this.pars.clickPixel/this.dems.content.height) * this.dems.y.area.height);
		}
		
		else if(this.pars.clickPercent){
			this.yClickMove = Math.ceil((this.pars.clickPercent/100) * this.dems.y.area.height);
		}
	},
	
	setIterationX: function(){
		
		if (this.pars.clickPixel) {
			this.xClickMove = Math.ceil((this.pars.clickPixel/this.dems.content.width) * this.dems.x.area.width);
		}
		
		else if(this.pars.clickPercent){
			this.xClickMove = Math.ceil((this.pars.clickPercent/100) * this.dems.x.area.width);
		}
	},
	
	scrollY: function(y){
		if (y > this.maxY) {
			y = this.maxY;
		}
		else if (y < 0) {
			y = 0;
		}
		this.eles.y.marker.style.top = y + 'px';
		this.moveContentY();
		
		return this
	},
	
	scrollX: function (x) {
		if (x < 0) {
			x = 0;
		}
		if (x > this.maxX) {
			x = this.maxX;
		}
		this.eles.x.marker.style.left = x + 'px'
		this.moveContentX();
	},
	
	scrollYNext: function(){
		var y = parseInt(this.eles.y.marker.getStyle('top')) + this.yClickMove;
		this.scrollY(y);
		return this
	},
	
	scrollYPrev: function(){
		var y = parseInt(this.eles.y.marker.getStyle('top')) - this.yClickMove;
		this.scrollY(y);
		return this
	},
	
	scrollXNext: function(){
		var x = parseInt(this.eles.x.marker.getStyle('left')) + this.xClickMove;
		this.scrollX(x);
		return this
	},
	
	scrollXPrev: function(){
		var x = parseInt(this.eles.x.marker.getStyle('left')) - this.xClickMove;
		this.scrollX(x);
		return this
	},
	
	scrollYBy: function(y){
		y = parseInt(this.eles.y.marker.getStyle('top')) - y;
		this.scrollY(y);
		return this
	},
	
	scrollXBy: function(x){
		x = parseInt(this.eles.x.marker.getStyle('left')) + x;
		this.scrollX(x);
		return this
	},
	
	setDems: function(){
		this.dems.holder = this.element.getDimensions();
		this.dems.content = {height: this.element.scrollHeight, width: this.element.scrollWidth};
		return this
	},
	
	setPositions: function(){
		this.dems.offset = {x:parseInt(Position.cumulativeOffset(this.element)[0]), y:parseInt(Position.cumulativeOffset(this.element)[1])};
		return this
	},
	
	sizeDemsY: function(){
		this.dems.y.holder = {width: parseInt(this.eles.y.holder.getStyle('width')), height: this.dems.holder.height};
		this.dems.y.prev = {width: parseInt(this.eles.y.prev.getStyle('width')), height: parseInt(this.eles.y.prev.getStyle('height'))};
		this.dems.y.next = {width: parseInt(this.eles.y.next.getStyle('width')), height: parseInt(this.eles.y.next.getStyle('height'))};
		this.dems.y.area.width = parseInt(this.eles.y.area.getStyle('width'));
		this.dems.y.area.height = this.dems.holder.height - this.dems.y.prev.height - this.dems.y.next.height;
		this.dems.y.marker.width = parseInt(this.eles.y.marker.getStyle('width'));
		this.dems.y.marker.height = Math.ceil((this.dems.holder.height/this.dems.content.height) * this.dems.y.area.height);
		
		//size elements
		this.eles.y.holder.style.height = this.dems.y.holder.height + 'px';
		this.eles.y.area.style.height = this.dems.y.area.height + 'px';
		this.eles.y.marker.style.height = this.dems.y.marker.height + 'px';
		
		//position elements
		this.eles.y.holder.style.left = this.dems.offset.x + this.dems.holder.width + 'px';
		this.eles.y.holder.style.top = this.dems.offset.y + 'px';
		
		this.maxY = this.dems.y.area.height - this.dems.y.marker.height;
		
		this.yDrag.pars.dirY.max = this.maxY
	},
	
	buildYBar: function(){
		if(!this.eles.y.holder){
			//create elements
			this.buildBarHTML('y');
			
			//apply actions to marker
			var para = {
				dirX: false,
				onStart: function(){
					this.yDragging = true;
				}.bind(this),
				onDrag: this.moveContentY.bind(this),
				onStop: function(){
					this.yDragging = false;
				}.bind(this),
				dirY: {
					min:0
				}
			}
			this.yDrag = new Df.Drag(this.eles.y.marker).set(para).enable();
			
			//apply actions to Buttons
			Event.observe(this.eles.y.next, 'mousedown', this.yNext.bind(this));
			Event.observe(this.eles.y.prev, 'mousedown', this.yPrev.bind(this));
			
			//apply actions to scroll area
			Event.observe(this.eles.y.area, 'mousedown', this.yMakeScrollDecision.bind(this));
		}
		return this
	},
	
	sizeDemsX: function(){
		//set dem vars
		this.dems.x.holder = {height: parseInt(this.eles.x.holder.getStyle('height')), width: this.dems.holder.width};
		this.dems.x.prev = {width: parseInt(this.eles.x.prev.getStyle('width')), height: parseInt(this.eles.x.prev.getStyle('height'))};
		this.dems.x.next = {width: parseInt(this.eles.x.next.getStyle('width')), height: parseInt(this.eles.x.next.getStyle('height'))};
		this.dems.x.area.height = parseInt(this.eles.x.area.getStyle('height'));
		this.dems.x.area.width = this.dems.holder.width - this.dems.x.prev.width - this.dems.x.next.width;
		this.dems.x.marker.height = parseInt(this.eles.x.marker.getStyle('height'));
		this.dems.x.marker.width = Math.ceil((this.dems.holder.width/this.dems.content.width) * this.dems.x.area.width);
		
		//size elements
		this.eles.x.holder.style.width = this.dems.x.holder.width + 'px';
		this.eles.x.area.style.width = this.dems.x.area.width + 'px';
		this.eles.x.marker.style.width = this.dems.x.marker.width + 'px';
		
		//position elements
		this.eles.x.holder.style.top = this.dems.offset.y + this.dems.holder.height + 'px';
		this.eles.x.holder.style.left = this.dems.offset.x + 'px';
		
		this.maxX = this.dems.x.area.width - this.dems.x.marker.width;
		
		this.xDrag.pars.dirX.max = this.maxX
		
	},
	
	buildXBar: function(){
		if(!this.eles.x.holder){
			
			//create elements
			this.buildBarHTML('x');
			
			//apply actions to marker
			var para = {
				dirY: false,
				onStart: function(){
					this.xDragging = true;
				}.bind(this),
				onDrag: this.moveContentX.bind(this),
				onStop: function(){
					this.xDragging = false;
				}.bind(this),
				dirX: {
					min:0
				}
			}
			
			this.xDrag = new Df.Drag(this.eles.x.marker).set(para).enable();
			
			//apply actions to Buttons
			Event.observe(this.eles.x.next, 'mousedown', this.xNext.bind(this));
			Event.observe(this.eles.x.prev, 'mousedown', this.xPrev.bind(this));
			
			//apply actions to scroll area
			Event.observe(this.eles.x.area, 'mousedown', this.xMakeScrollDecision.bind(this));
		}
		return this
	},
	
	wheelControl: function(e){
		if(e.memo.delta > 0){
			this.scrollYPrev();
		}
		else if(e.memo.delta < 0){
			this.scrollYNext();
		}
		
		return this
	},
	
	xMakeScrollDecision: function(event){
		if(!this.xDragging){
			this.xTo(event);
		}
	},
	
	yMakeScrollDecision: function(event){
		if(!this.yDragging){
			this.yTo(event);
		}
	},
		
	yNext: function(event){
		this.yClickStatusNext = true
		this.yNextClick(this.pars.clickPause);
	},
		
	/** @private */
	yPrev: function(event){
		this.yClickStatusPrev = true
		this.yPrevClick(this.pars.clickPause);
	},
		
	/** @private */
	xNext: function(event){
		this.xClickStatusNext = true
		this.xNextClick(this.pars.clickPause);
	},
		
	/** @private */
	xPrev: function(event){
		this.xClickStatusPrev = true
		this.xPrevClick(this.pars.clickPause);
	},
		
	/** @private */
	yPrevClick: function(i){
		if(this.yClickStatusPrev){
			this.scrollYPrev();
			setTimeout(function(){
				this.yPrevClick(this.pars.clickRepeat);
			}.bind(this), i);
		}
	},
		
	/** @private */
	yNextClick: function(i){
		if(this.yClickStatusNext){
			this.scrollYNext();
			setTimeout(function(){
				this.yNextClick(this.pars.clickRepeat)
			}.bind(this), i);
		}
	},
		
	/** @private */
	xPrevClick: function(i){
		if(this.xClickStatusPrev){
			this.scrollXPrev();
			setTimeout(function(){
				this.xPrevClick(this.pars.clickRepeat);
			}.bind(this), i);
		}
	},
		
	/** @private */
	xNextClick: function(i){
		if(this.xClickStatusNext){
			this.scrollXNext();
			setTimeout(function(){
				this.xNextClick(this.pars.clickRepeat);
			}.bind(this), i);
		}
	},
		
	/** @private */
	yTo: function(event){
		Event.stop(event);
		var top = (Event.pointerY(event) - this.dems.offset.y - this.dems.y.prev.height) - parseInt((this.dems.y.marker.height/2));
		if(top<0){
			top = 0;
		}else if(top > this.maxY){
			top = this.maxY;
		}
		this.eles.y.marker.style.top = top + 'px';
		this.moveContentY();
	},
		
	/** @private */
	xTo: function(event){
		Event.stop(event);
		var left = (Event.pointerX(event) - this.dems.offset.x - this.dems.x.prev.width) - parseInt((this.dems.x.marker.width/2));
		if(left<0){
			left = 0;
		}else if(left > this.maxX){
			left = this.maxX;
		}
		this.eles.x.marker.style.left = left + 'px';
		this.moveContentX();
	},
		
	/** @private */
	moveContentY: function(){
		var percent = parseInt(this.eles.y.marker.getStyle('top')) / (this.dems.y.area.height - this.dems.y.marker.height);
		this.element.scrollTop =  parseInt((this.dems.content.height - this.dems.holder.height) * percent);
		return this;
	},
		
	/** @private */
	moveContentX:function(){
		var percent = parseInt(this.eles.x.marker.getStyle('left')) / (this.dems.x.area.width - this.dems.x.marker.width);
		this.element.scrollLeft =  parseInt((this.dems.content.width - this.dems.holder.width) * percent);
		return this
	},
		
	/** @private */
	buildBarHTML: function(d){
		this.eles[d].holder = Df.e('div', document.body,{ className:this.pars.classNames[d].holder } );
		this.eles[d].prev = Df.e('div', this.eles[d].holder,{ className:this.pars.classNames[d].prev } );
		this.eles[d].area = Df.e('div', this.eles[d].holder,{ className:this.pars.classNames[d].area } );
		this.eles[d].marker = Df.e('div', this.eles[d].area,{ className:this.pars.classNames[d].marker } );
		this.eles[d].next = Df.e('div', this.eles[d].holder,{ className:this.pars.classNames[d].next } );
	}
});



