/*
Drag.Move.implement({
	
	start: function(event){
		this.container = $(this.options.container);
		if (this.container){
			var cont = this.container.getCoordinates();
			var el = this.element.getCoordinates();
			
			if( this.options.relative != null )
				var rel = this.options.relative.getCoordinates();
			else
				var rel = { left: 0, top: 0 };
			
			cont.left -= rel.left;
			cont.right -= rel.left;
			cont.top -= rel.top;
			cont.bottom -= rel.top;
			
			el.left -= rel.left;
			el.right -= rel.left;
			el.top -= rel.top;
			el.bottom -= rel.top;
			
			if (this.position == 'absolute'){
				this.options.limit = {
					'x': [cont.left, cont.right - el.width],
					'y': [cont.top, cont.bottom - el.height]
				};
			} else {
				var diffx = el.left - this.element.getStyle('left').toInt();
				var diffy = el.top - this.element.getStyle('top').toInt();
				this.options.limit = {
					'y': [-(diffy) + cont.top, cont.bottom - diffy - el.height],
					'x': [-(diffx) + cont.left, cont.right - diffx - el.width]
				};
			}
			
		}
		
		this.fireEvent('onBeforeStart', this.element);
		this.mouse.start = event.page;
		var limit = this.options.limit;
		this.limit = {'x': [], 'y': []};
		for (var z in this.options.modifiers){
			this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
			this.mouse.pos[z] = event.page[z] - this.value.now[z];
			if (limit && limit[z]){
				for (var i = 0; i < 2; i++){
					if ($chk(limit[z][i])) this.limit[z][i] = limit[z][i].apply ? limit[z][i].call(this) : limit[z][i];
				}
			}
		}
		this.element.limit = this.limit;
		this.bound.drag = this.drag.bindWithEvent(this);
		this.bound.stop = this.stop.bind(this);
		this.bound.move = this.options.snap ? this.checkAndDrag.bindWithEvent(this) : this.bound.drag;
		document.addEvent('mousemove', this.bound.move);
		document.addEvent('mouseup', this.bound.stop);
		this.fireEvent('onStart', this.element);
		event.stop();
	}
	
} );
*/
var ScrollWindow = new Class( {
	
	options: {
		onMove: Class.empty
	},
	
	initialize: function ( main, area, content, scrollBars, buttons, mouseWheelSpeed, options ) {
		
		this.setOptions( options );
		this.main = $(main);
		this.area = $(area);
		this.content = $(content);
		this.scrollBars = new Array();
		this.buttons = new Array();
		
		this.mouseWheelSpeed = mouseWheelSpeed;
		
		this.percPositions = { x: 0, y: 0 };
		this.actBttScroll = false;
		
		this.area.range = { x: this.area.getSize().scrollSize.x - this.area.getSize().size.x, y: this.area.getSize().scrollSize.y - this.area.getSize().size.y };
		this.area.scrollTo( 0, 0 );
		this.area.addEvent( window.gecko?'DOMMouseScroll':'mousewheel', this.wheelScroll.bindAsEventListener( this ) );
		
		scrollBars.each( function ( obj, num ) {
			this.scrollBars.push( {
				bar: $(obj[0]),
				scroller: $(obj[1]),
				orientation: obj[2],
				step: new Object(),
				percPositions: { x: 0, y: 0 },
				range: {
					x: $(obj[0]).getSize().size.x - $(obj[1]).getSize().size.x,
					y: $(obj[0]).getSize().size.y - $(obj[1]).getSize().size.y
				},
				start: {
					x: $(obj[1]).getStyle( 'left' ).toInt(),
					y: $(obj[1]).getStyle( 'top' ).toInt()
				}
			} );
		}, this );
		
		buttons.each( function ( obj, num ) {
			switch( $type(obj) )
			{
				case 'array':
					this.buttons.push( {
						button: $(obj[0]),
						orientation: obj[1],
						direction: obj[2],
						step: obj[3],
						percStep: 100 * obj[3] / this.area.range[obj[1]]
					} );
					break;
				case 'object':
					obj.button = $(obj.button);
					obj.percStep = 100 * obj.step / this.area.range[obj.orientation];
					this.buttons.push( obj );
					break;
			}
		}, this );
		
		this.orientationSizes = { 'x': 'width', 'y': 'height' };
		this.orientationPositions = { 'x': 'left', 'y': 'top' };
		
		this.scrollEffect = new Fx.Scroll( this.area, { transition: Fx.Transitions.sineInOut, duration: 1 } );
		
		this.scrollBars.each( function ( obj, num ) {
			obj.scroller.rel = obj;
			for( var i=0; i<obj.orientation.length; i++ )
			{
				var key = this.orientationSizes[obj.orientation[i]];
				var divider = ( obj.bar.getCoordinates()[key] - obj.scroller.getCoordinates()[key] );
				if( divider != 0 )
					obj.step[obj.orientation[i]] = ( this.area.getSize().scrollSize[obj.orientation[i]] - this.area.getCoordinates()[key] ) / divider;
			}
			
			obj.scroller.makeDraggable( {
				container: obj.bar,
				relative: this.main,
				onDrag: this.onDrag.bind( this )
			} );
			
			obj.bar.addEvent( 'click', this.onBarClick.bindAsEventListener( this, obj ) );
		}, this );
		
		this.buttons.each( function ( obj, num ) {
			obj.button.addEvent( 'mousedown', this.startButtonScroll.bindAsEventListener( this, obj ) );
			document.body.onmouseup = this.stopButtonScroll.bindAsEventListener( this, obj );
		}, this );
	},
	
	wheelScroll: function ( event ) {
		event = new Event( event );
		var scr = {
			x: this.area.getSize().scroll.x,
			y: this.area.getSize().scroll.y
		};
		this.percPositions.y = Math.max( 0, Math.min( 100, this.percPositions.y - event.wheel * this.mouseWheelSpeed ) );
		scr.y = this.percPositions.y * this.area.range.y / 100;
		this.area.scrollTo( scr.x, scr.y );
		this.updateScrollBars( null );
	},
	
	startButtonScroll: function ( event, obj ) {
		this.doButtonScroll( obj );
		var button = event.button;
		event = new Event( event );
		if( window.ie )
			var _left = 1;
		if( window.gecko )
			var _left = 0;
		switch( button )
		{
			case _left:
				var mouseButton = 'left';
				break;
			case 2:
				var mouseButton = 'right';
				break;
			default:
				var mouseButton = '';
				break;
		}
		if( mouseButton == 'left' )
		{
			obj.button.addClass( 'sb_bttMouseDown' );
			this.actBttScroll = window.setInterval( this.doButtonScroll.bind( this, obj ), 75 );
		}
	},
	
	stopButtonScroll: function ( event, obj ) {
		var button = event.button;
		event = new Event( event );
		if( window.ie )
			var _left = 1;
		if( window.gecko )
			var _left = 0;
		switch( button )
		{
			case _left:
				var mouseButton = 'left';
				break;
			case 2:
				var mouseButton = 'right';
				break;
			default:
				var mouseButton = '';
				break;
		}
		if( mouseButton == 'left' && this.actBttScroll )
		{
			obj.button.removeClass( 'sb_bttMouseDown' );
			window.clearInterval( this.actBttScroll );
		}
	},
	
	onButtonClick: function ( event, bttObj ) {
		var orientation = bttObj.orientation;
		var scr = {
			x: this.area.getSize().scroll.x,
			y: this.area.getSize().scroll.y
		};
		this.percPositions[orientation] = Math.max( 0, Math.min( 100, this.percPositions[orientation] + bttObj.direction * bttObj.percStep ) );
		scr[orientation] = this.percPositions[orientation] * this.area.range[orientation] / 100;
		this.area.scrollTo( scr.x, scr.y );
		this.updateScrollBars( null );
		this.fireEvent( 'onMove', [ scr.x, scr.y ] );
	},
	
	doButtonScroll: function ( bttObj ) {
		var orientation = bttObj.orientation;
		var scr = {
			x: this.area.getSize().scroll.x,
			y: this.area.getSize().scroll.y
		};
		this.percPositions[orientation] = Math.max( 0, Math.min( 100, this.percPositions[orientation] + bttObj.direction * bttObj.percStep ) );
		scr[orientation] = this.percPositions[orientation] * this.area.range[orientation] / 100;
		this.area.scrollTo( scr.x, scr.y );
		this.updateScrollBars( null );
		this.fireEvent( 'onMove', [ scr.x, scr.y ] );
	},
	
	onDrag: function ( obj ) {
		obj = obj.rel;
		var scr = {
			x: this.area.getSize().scroll.x,
			y: this.area.getSize().scroll.y
		};
		for( var i=0; i<obj.orientation.length; i++ )
		{
			var actPos = obj.scroller.getStyle( this.orientationPositions[obj.orientation[i]] ).toInt() - obj.start[obj.orientation[i]];
			scr[obj.orientation[i]] = Math.ceil( actPos * obj.step[obj.orientation[i]] );
			obj.percPositions[obj.orientation[i]] = 100 * scr[obj.orientation[i]] / this.area.range[obj.orientation[i]];
			this.percPositions[obj.orientation[i]] = obj.percPositions[obj.orientation[i]];
		}
		this.area.scrollTo( scr.x, scr.y );
		this.updateScrollBars( obj );
		this.fireEvent( 'onMove', [ scr.x, scr.y ] );
	},
	
	onBarClick: function ( event, obj ) {
		event = new Event( event );
		var clickX = event.page.x;
		var clickY = event.page.y;
		
		var clickPoint = {
			x: Math.max( 0, clickX - obj.bar.getCoordinates().left - Math.floor( obj.scroller.getSize().size.x / 2 ) ),
			y: Math.max( 0, clickY - obj.bar.getCoordinates().top - Math.floor( obj.scroller.getSize().size.y / 2 ) )
		};
		
		var scr = {
			x: this.area.getSize().scroll.x,
			y: this.area.getSize().scroll.y
		};
		if( obj.range.x > 0 )
			this.percPositions.x = Math.max( 0, Math.min( 100, 100 * clickPoint.x / obj.range.x ) );
		if( obj.range.y > 0 )
			this.percPositions.y = Math.max( 0, Math.min( 100, 100 * clickPoint.y / obj.range.y ) );
		scr.x = this.percPositions.x * this.area.range.x / 100;
		scr.y = this.percPositions.y * this.area.range.y / 100;
		this.area.scrollTo( scr.x, scr.y );
		this.updateScrollBars( null );
		this.fireEvent( 'onMove', [ scr.x, scr.y ] );
	},
	
	scrollTo: function ( x, y ) {
		this.percPositions.x = 100 * x / this.area.range.x;
		this.percPositions.y = 100 * y / this.area.range.y;
		this.area.scrollTo( x, y );
		this.updateScrollBars( null );
		this.fireEvent( 'onMove', [ x, y ] );
	},
	
	updateScrollBars: function ( obj ) {
		for( var i=0; i<this.scrollBars.length; i++ )
		{
			if( this.scrollBars[i] != obj )
				this.setScrollbarPercentage( this.scrollBars[i] );
		}
	},
	
	setScrollbarPercentage: function ( obj ) {
		if( obj.percPositions.x != this.percPositions.x ) {
			obj.percPositions.x = this.percPositions.x;
			obj.scroller.setStyle( 'left', Math.floor( obj.start.x + this.percPositions.x * obj.range.x / 100 ) + 'px' );
		}
		if( obj.percPositions.y != this.percPositions.y ) {
			obj.percPositions.y = this.percPositions.y;
			obj.scroller.setStyle( 'top', Math.floor( obj.start.y + this.percPositions.y * obj.range.y / 100 ) + 'px' );
		}
	}
	
} );

ScrollWindow.implement( new Events );
ScrollWindow.implement( new Options );
