Scroller = Class.create();

Scroller.prototype = {
	
	initialize: function (type,objs,interval,speed) {
		this.type = type;
		this.objs = objs;
		this.interval = interval;
		this.speed = speed;
		this.intMoveH = this.intMoveV = "";
		this.startX = this.objs.container.offsetLeft;
		this.startY = this.objs.container.offsetTop;
		this.endX = this.endY = 0;
		this.mouseWheelEvent = (document.all) ?"mousewheel" :"DOMMouseScroll";
		this.scrollingVertical = this.scrollingHorizontal = true;
		this.scrollTopOld = this.scrollLeftOld = 0;
		this.intMoveV = this.intMoveH = null;
	},
	
	init: function () {
		
		if (this.type=="vertical"||this.type=="multi") {
			if (this.objs.container.offsetHeight>this.objs.mask.offsetHeight) {
				Event.observe(this.objs.scUp, "mouseover", this.moveUp.bindAsEventListener(this));
				Event.observe(this.objs.scDn, "mouseover", this.moveDown.bindAsEventListener(this));
				Event.observe(this.objs.scUp, "mouseout", this.stop.bindAsEventListener(this));
				Event.observe(this.objs.scDn, "mouseout", this.stop.bindAsEventListener(this));
				this.endY = parseInt(this.objs.container.style.top) - this.objs.container.offsetHeight + this.objs.mask.offsetHeight;
				this.setVerticalCursor();
			}
			else this.hideVerticalScrollElems();
		}
		if (this.type=="horizontal"||this.type=="multi") {
			if (this.objs.container.offsetWidth>this.objs.mask.offsetWidth) {
				Event.observe(this.scLeft.scLeft, "mouseover", this.moveLeft.bindAsEventListener(this));
				Event.observe(this.scRight.scRight, "mouseover", this.moveRight.bindAsEventListener(this));
				Event.observe(this.scLeft.scLeft, "mouseout", this.stop.bindAsEventListener(this));
				Event.observe(this.scRight.scRight, "mouseout", this.stop.bindAsEventListener(this));
				this.endX = parseInt(this.objs.container.style.left) - this.objs.container.offsetWidth + this.objs.mask.offsetWidth;
				this.setHorizontalCursor();
			}
			else this.hideHorizontalScrollElems();
		}
		
	},
	
	moveDown: function () {
		this.cursor.speedHCheck = 0;
		if (this.intMoveV==null) this.intMoveV = new PeriodicalExecuter(this.down.bind(this),this.interval/1000);
		else {
			this.intMoveV.callback = this.down.bind(this);
			this.intMoveV.registerCallback();
		}
	},
	
	moveUp: function () {
		this.cursor.speedHCheck = 0;
		if (this.intMoveV==null) this.intMoveV = new PeriodicalExecuter(this.up.bind(this),this.interval/1000);
		else {
			this.intMoveV.callback = this.up.bind(this);
			this.intMoveV.registerCallback();
		}
	},
	
	moveLeft: function () {
		this.cursor.speedVCheck = 0;
		if (this.intMoveH==null) this.intMoveH = new PeriodicalExecuter(this.left.bind(this),this.interval/1000);
		else {
			this.intMoveH.callback = this.left.bind(this);
			this.intMoveH.registerCallback();
		}
	},
	
	moveRight: function () {
		this.cursor.speedVCheck = 0;
		if (this.intMoveH==null) this.intMoveH = new PeriodicalExecuter(this.right.bind(this),this.interval/1000);
		else {
			this.intMoveH.callback = this.right.bind(this);
			this.intMoveH.registerCallback();
		}
	},
	
	hideVerticalScrollElems: function () {
		this.objs.scUp.style.visibility = this.objs.scDn.style.visibility = this.objs.cursorTop.style.visibility = "hidden";
		this.scrollingVertical = false;
	},
	
	hideHorizontalScrollElems: function () {
		this.objs.scLeft.style.visibility = this.objs.scRight.style.visibility = this.objs.cursorLeft.style.visibility = "hidden";
		this.scrollingHorizontal = false;
	},
	
	up: function () {
		this.objs.mask.scrollTop -= this.speed;
		this.cursor.speedHCheck = (this.cursor.speedHCheck<1) ?this.cursor.speedHCheck + this.cursor.speed :0;
		if (this.cursor.speedHCheck>=1) this.objs.cursorTop.style.top = this.objs.cursorTop.offsetTop - Math.round(this.cursor.speedHCheck) + "px";
		if (this.objs.mask.scrollTop==this.scrollTopOld) {
			this.stop();
			this.objs.cursorTop.style.top = this.cursor.startY + "px";
		}
		this.scrollTopOld = this.objs.mask.scrollTop;
	},
	
	down: function () {
		this.objs.mask.scrollTop += this.speed;
		this.cursor.speedHCheck = (this.cursor.speedHCheck<1) ?this.cursor.speedHCheck + this.cursor.speed :0;
		if (this.cursor.speedHCheck>=1) this.objs.cursorTop.style.top = this.objs.cursorTop.offsetTop + Math.round(this.cursor.speedHCheck) + "px";
		if (this.objs.mask.scrollTop==this.scrollTopOld) {
			this.stop();
			this.objs.cursorTop.style.top = this.cursor.endY + "px";
		}
		this.scrollTopOld = this.objs.mask.scrollTop;
	},
	
	left: function () {
		this.objs.mask.scrollLeft -= this.speed;
		this.cursor.speedVCheck = (this.cursor.speedVCheck<1) ?this.cursor.speedVCheck + this.cursor.speed :0;
		if (this.cursor.speedVCheck>=1) this.objs.cursorLeft.style.left = this.objs.cursorLeft.offsetLeft - Math.round(this.cursor.speedVCheck) + "px";
		if (this.objs.mask.scrollLeft==this.scrollLeftOld) {
			this.stop();
			this.objs.cursorLeft.style.left = this.cursor.startX + "px";
		}
		this.scrollLeftOld = this.objs.mask.scrollLeft;
	},
	
	right: function () {
		this.objs.mask.scrollLeft += this.speed;
		this.cursor.speedVCheck = (this.cursor.speedVCheck<1) ?this.cursor.speedVCheck + this.cursor.speed :0;
		if (this.cursor.speedVCheck>=1) this.objs.cursorLeft.style.left = this.objs.cursorLeft.offsetLeft + Math.round(this.cursor.speedVCheck) + "px";
		if (this.objs.mask.scrollLeft==this.scrollLeftOld) {
			this.stop();
			this.objs.cursorLeft.style.left = this.cursor.endX + "px";
		}
		this.scrollLeftOld = this.objs.mask.scrollLeft;
	},
	
	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();
	},
	
	reset: function () {
		if (this.scrollingVertical) {
			if (this.type=="vertical"||this.type=="multi") {
				this.objs.mask.scrollTop = 0;
				this.objs.cursorTop.style.top = this.cursor.startY;
			}
		}
		if (this.scrollingHorizontal) {
			if (this.type=="horizontal"||this.type=="multi") {
				this.objs.mask.scrollLeft = 0;
				this.objs.cursorLeft.style.left = this.cursor.startX;
			}
		}
	},
	
	setVerticalCursor: function () {
		this.objs.cursorTop.style.top = this.objs.cursorTop.offsetTop + "px";
		this.cursor = { 
						startY:this.objs.cursorTop.offsetTop,
						endY:this.objs.cursorTop.offsetTop + this.objs.cursorTop.offsetHeight,
						coeffY:this.objs.mask.offsetHeight / this.objs.container.offsetHeight,
						speedHCheck:0
					};
		this.objs.cursorTop.style.height = this.objs.cursorTop.offsetHeight * this.cursor.coeffY + "px";
		this.cursor.endY -= this.objs.cursorTop.offsetHeight;
		this.cursor.speed = this.speed * this.cursor.coeffY;
		Event.observe(this.objs.mask, this.mouseWheelEvent, this.mouseWheelVChecker.bindAsEventListener(this));
	},

	setHorizontalCursor: function () {
		this.objs.cursorLeft.style.left = this.objs.cursorLeft.offsetLeft + "px";
		this.cursor = { 
						startX:this.objs.cursorLeft.offsetLeft,
						endX:this.objs.cursorLeft.offsetLeft + this.objs.cursorLeft.offsetWidth,
						coeffX:this.objs.mask.offsetWidth / this.objs.container.offsetWidth,
						speedVCheck:0
					};
		this.objs.cursorLeft.style.width = this.objs.cursorLeft.offsetWidth * this.cursor.coeffX + "px";
		this.cursor.endX -= this.objs.cursorLeft.offsetWidth;
		this.cursor.speed = this.speed * this.cursor.coeffX;
	},
	
	mouseWheelVChecker: function (e)  {
		(Event.wheel(e)==-1) ?this.down() :this.up();
	},
	
	moveToAnchor: function (label) {
		if (this.scrollingVertical) {
			if (this.type=="vertical"||this.type=="multi") {
				this.objs.mask.scrollTop = $(label).offsetTop;
				var cursorToMove = $(label).offsetTop * this.cursor.coeffY;
				this.objs.cursorTop.style.top = (this.cursor.startY + cursorToMove<this.cursor.endY) ?this.cursor.startY + cursorToMove + "px" :this.cursor.endY + "px";
			}
		}
		if (this.scrollingHorizontal) {
			if (this.type=="horizontal"||this.type=="multi") {
				this.objs.mask.scrollLeft = $(label).offsetLeft;
				var cursorToMove = $(label).offsetLeft * this.cursor.coeffX;
				this.objs.cursorLeft.style.left = (this.cursor.startX + cursorToMove<this.cursor.endX) ?this.cursor.startX + cursorToMove + "px" :this.cursor.endX + "px";
			}
		}
	}

}

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);
	}
});