Aheuh.Scroller = Class.create({
	
	initialize: function (type,objs,interval,speed) {
		this._type = type;
		this._objs = objs;
		this._interval = interval;
		this._speed = speed;
		this._mouseWheelEvent = (document.all) ?"mousewheel" :"DOMMouseScroll";
		this._scrollingV = this._scrollingH = false;
		this._scrollVOld = this._scrollHOld = 0;
		this._intMoveV = this._intMoveH = null;
	},
	
	init: function () {
		if (this._type=="vertical"||this._type=="multi") {
			if (this._objs.mask.scrollHeight>this._objs.mask.offsetHeight) { this.viewScrollElems(this._type,"visible",true); }
			else { this.viewScrollElems(this._type,"hidden",false); }			
			Event.observe(this._objs.scUp, "mouseover", this._moveUpDown.bind(this,-1));
			Event.observe(this._objs.scDn, "mouseover", this._moveUpDown.bind(this,1));
			Event.observe(this._objs.scUp, "mouseout", this.stop.bind(this));
			Event.observe(this._objs.scDn, "mouseout", this.stop.bind(this));
			Event.observe(this._objs.mask, this._mouseWheelEvent, this._mouseWheelVChecker.bindAsEventListener(this));				
			this._setVerticalCursor();		
		}
		if (this._type=="horizontal"||this._type=="multi") {
			if (this._objs.mask.scrollWidth>this._objs.mask.offsetWidth) { this.viewScrollElems(this._type,"visible",true); }
			else { this.viewScrollElems(this._type,"hidden",false); }			
			Event.observe(this._objs.scLeft, "mouseover", this._moveLeftRight.bind(this,-1));
			Event.observe(this._objs.scRight, "mouseover", this._moveLeftRight.bind(this,1));
			Event.observe(this._objs.scLeft, "mouseout", this.stop.bind(this));
			Event.observe(this._objs.scRight, "mouseout", this.stop.bind(this));
			this._setHorizontalCursor();
		}		
	},
	
	_moveUpDown: function (move) {
		if (this._intMoveV==null) { this._intMoveV = new PeriodicalExecuter(this._upDown.bind(this,move),this._interval/1000); }
		else {
			this._intMoveV.callback = this._upDown.bind(this,move);
			this._intMoveV.registerCallback();
		}
	},
	
	_moveLeftRight: function (move) {
		if (this._intMoveH==null) { this._intMoveH = new PeriodicalExecuter(this._leftRight.bind(this,move),this._interval/1000); }
		else {
			this._intMoveH.callback = this._leftRight.bind(this,move);
			this._intMoveH.registerCallback();
		}
	},
	
	_upDown: function (move) {
		this._objs.mask.scrollTop += this._speed*move;
		this._setUpDownCursor();
		if (this._objs.mask.scrollTop==this._scrollVOld) { this.stop(); }
		this._scrollVOld = this._objs.mask.scrollTop;
	},
	
	_leftRight: function (move) {
		this._objs.mask.scrollLeft += this._speed*move;
		this._setLeftRightCursor();
		if (this._objs.mask.scrollLeft==this._scrollHOld) { this.stop(); }
		this._scrollHOld = this._objs.mask.scrollLeft;
	},
	
	_setUpDownCursor: function () {
		this._objs.cursorV.style.top = this.cursorV.startY+this._objs.mask.scrollTop*this.cursorV.coeffY+"px";
	},
	
	_setLeftRightCursor: function () {
		this._objs.cursorH.style.left = this.cursorH.startX+this._objs.mask.scrollLeft*this.cursorH.coeffX+"px";
	},
	
	viewScrollElems: function (type,visibility,scrolling) {
		if (type=="vertical") {
			this.showScrollElems(type,visibility);
			if (scrolling!="noChange") { this._scrollingV = scrolling; }
		}
		else if (type=="horizontal") {
			this.showScrollElems(type,visibility);
			if (scrolling!="noChange") { this._scrollingH = scrolling; }
		}
	},
	
	showScrollElems: function (type,visibility) {
		if (type=="vertical") {
			this._objs.scrollbar.style.visibility = this._objs.scUp.style.visibility = this._objs.scDn.style.visibility = this._objs.cursorV.style.visibility = visibility;
		}
		else if (type=="horizontal") {
			this._objs.scrollbar.style.visibility = this._objs.scLeft.style.visibility = this._objs.scRight.style.visibility = this._objs.cursorH.style.visibility = visibility;
		}
	},
	
	stop: function () {
		if (this._type=="vertical"&&this._intMoveV!=null||this._type=="multi"&&this._intMoveV!=null) { this._intMoveV.stop(); }
		if (this._type=="horizontal"&&this._intMoveH!=null||this._type=="multi"&&this._intMoveH!=null) { this._intMoveH.stop(); }
	},
	
	_setVerticalCursor: function () {		
		
		if (!this.cursorV) {
			this.cursorV = {
				startY:this._objs.cursorV.offsetTop,
				initHeight:this._objs.cursorV.offsetHeight,
				diff:this._objs.mask.offsetHeight-this._objs.cursorV.offsetHeight,
				endY:this._objs.cursorV.offsetTop+this._objs.cursorV.offsetHeight
			};
			Event.observe(this._objs.scrollbarBgV, "click", this._moveUpDownByBg.bindAsEventListener(this));
		}
		else {
			this._objs.cursorV.style.top = this.cursorV.startY+"px";
			this._objs.cursorV.style.height = this.cursorV.initHeight+"px";
		}
		this.cursorV.coeffY = (this._objs.mask.offsetHeight-this.cursorV.diff)/(this._objs.mask.scrollHeight-this.cursorV.diff);
		if (this.cursorV.coeffY<0) { this.cursorV.coeffY = 0; }
		
		this._objs.cursorV.style.height = this._objs.cursorV.offsetHeight*this.cursorV.coeffY+"px";
		if (!this.myDragV) {
			this.myDragV = new Aheuh.Drag(this._objs.cursorV,this._objs.cursorV.offsetLeft,this._objs.cursorV.offsetLeft,this.cursorV.startY,this.cursorV.endY,this.moveToY.bind(this));	
		}
		else {
			this.myDragV.reload(this._objs.cursorV.offsetLeft,this._objs.cursorV.offsetLeft,this.cursorV.startY,this.cursorV.endY);
		}
		
		this._setUpDownCursor();
		this.moveToY();
		
	},

	_setHorizontalCursor: function () {
		
		if (!this.cursorH) {
			this.cursorH = {
				startX:this._objs.cursorV.offsetLeft,
				initWidth:this._objs.cursorV.offsetWidth,
				diff:this._objs.mask.offsetWidth-this._objs.cursorV.offsetWidth
			};
			Event.observe(this._objs.scrollbarBgH, "click", this._moveLeftRightByBg.bind(this));
		}
		else {
			this._objs.cursorH.style.left = this.cursorH.startX+"px";
			this._objs.cursorH.style.width = this.cursorH.initWidth+"px";
		}		
		this.cursorH.coeffX = (this._objs.mask.offsetWidth-this.cursorH.diff)/(this._objs.mask.scrollWidth-this.cursorH.diff);
		if (this.cursorH.coeffX<0) { this.cursorH.coeffX = 0; }
		
		this._objs.cursorH.style.width = this._objs.cursorH.offsetWidth*this.cursorV.coeffX+"px";
		this.cursorH.endX = this.cursorH.startX+this.cursorV.initWidth;
		if (!this.myDragH) {
			this.myDragH = new Aheuh.Drag(this._objs.cursorH,this.cursorH.startX,this.cursorH.endX,this._objs.cursorV.offsetTop,this._objs.cursorV.offsetTop,this.moveToX.bind(this));	
		}
		else {
			this.myDragH.reload(this.cursorH.startX,this.cursorH.endX,this._objs.cursorV.offsetTop,this._objs.cursorV.offsetTop);
		}
		
		this._setLeftRightCursor();
		this.moveToX();
		
	},
	
	_mouseWheelVChecker: function (e)  {
		e.stop();
		if (this._scrollingV) { this._upDown(Event.Wheel(e)*-1); }
	},
	
	moveToY: function () {
		this._objs.mask.scrollTop = (parseInt(this._objs.cursorV.style.top)-this.cursorV.startY)/this.cursorV.coeffY;
	},
	
	moveToX: function () {
		this._objs.mask.scrollLeft = (parseInt(this._objs.cursorV.style.left)-this.cursorV.startX)/this.cursorV.coeffX;
	},
	
	moveToAnchor: function (label) {
		if (this._scrollingV) {
			if (this._type=="vertical"||this._type=="multi") {
				this._objs.mask.scrollTop = $(label).offsetTop;
				var cursorToMove = $(label).offsetTop * this.cursorV.coeffY;
				this._objs.cursorV.style.top = (this.cursorV.startY+cursorToMove+this._objs.cursorV.offsetHeight<this.cursorV.endY) ?this.cursorV.startY + cursorToMove + "px" :this.cursorV.endY - this._objs.cursorV.offsetHeight + "px";
			}
		}
		if (this._scrollingH) {
			if (this._type=="horizontal"||this._type=="multi") {
				this._objs.mask.scrollLeft = $(label).offsetLeft;
				var cursorToMove = $(label).offsetLeft * this.cursorH.coeffX;
				this._objs.cursorH.style.left = (this.cursorH.startX+cursorToMove+this._objs.cursorH.offsetWidth<this.cursorH.endX) ?this.cursorH.startX + cursorToMove + "px" :this.cursorH.endX - this._objs.cursorH.offsetWidth + "px";
			}
		}
	},
	
	reload: function () {
		if (this._type=="vertical"||this._type=="multi") {
			if (this._objs.mask.scrollHeight>this._objs.mask.offsetHeight) {
				this._fixFirefox();
				this._objs.mask.scrollTop = 0;
				this._setVerticalCursor();
				this.viewScrollElems(this._type,"visible",true);
			}
			else { this.viewScrollElems(this._type,"hidden",false); }
		}
		if (this._type=="horizontal"||this._type=="multi") {
			if (this._objs.mask.scrollWidth>this._objs.mask.offsetWidth) {
				this._fixFirefox();
				this._objs.mask.scrollLeft = 0;
				this._setHorizontalCursor();
				this.viewScrollElems(this._type,"visible",true);
			}
			else { this.viewScrollElems(this._type,"hidden",false); }
		}		
	},
	
	_fixFirefox: function () {
		var d = document.createElement("b");
		this._objs.mask.appendChild(d);
	},
	
	_moveUpDownByBg: function (e) {
		var yMouse = Event.pointerY(e);
		var o = this._objs.cursorV;
		var move = (yMouse>o.offsetTop+o.offsetHeight) ?1 :-1;
		this._objs.mask.scrollTop += this.cursorV.initHeight*move;
		this._setUpDownCursor();
	},
	
	_moveLeftRightByBg: function (e) {
		var xMouse = Event.pointerX(e);
		var o = this._objs.cursorH;
		var move = (xMouse>o.offsetLeft+o.offsetWidth) ?1 :-1;
		this._objs.mask.scrollLeft += this.cursorH.initWidth*move;
		this._setLeftRightCursor();
	}
	
});