////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mouse handling mechanism 
////////////////////////////////////////////////////////////////////////////////////////////////////////////

MouseDevice = Class.create(
{	
	initialize : function()
	{
		this.aListeners = new Array();
		this.iMousePosX = 0;
		this.iMousePosY = 0;
		this.iMoveX = 0;
		this.iMoveY = 0;
		this.iMouseLastPosX = 0;
		this.iMouseLastPosY = 0;
		
		this.bLeftMouseButtonPressed = false;
		this.bRightMouseButtonPressed = false;
		
		//click and doubleclick stuff
		this.clickTimerId = null;
		this.checkForDoubleClick = false;
		//needed to check mousemovement during doubleclick
		this.iCheckDoubleClickPosX = 0;
		this.iCheckDoubleClickPosY = 0;
		
		this.bIsSafari = g_isSafari(); 
		
		
		
		//listen to events
		
		//mouseWheel
		if (window.addEventListener)
		        // DOMMouseScroll is for mozilla. 
		        window.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false);
		// IE/Opera. 
		window.onmousewheel = document.onmousewheel = this.onMouseWheel.bind(this);
		
		//mouseEvents
		
		if( window.onmousedown ) 
		{
			this.origOnMouseDown = window.onmousedown; 
			this.origOnMouseUp = window.onmouseup;
			this.origOnMouseMove = window.onmousemove;
			this.origOnMouseOut = window.onmouseout;
			this.origOnMouseDrag = window.onmousedrag;
			//this.origOnMouseEnter= window.ondragenter;
			
			window.onmousedown = this.onMouseDown.bind(this) ;
			window.onmouseup = this.onMouseUp.bind(this) ;
			window.onmousemove = this.onMouseMove.bind(this) ;
			window.onmouseout = this.onMouseOut.bind(this) ;
			//window.onmousedrag = this.onMouseDrag.bind(this);
			
		}
		else 
		{
			// IE
			this.origOnMouseDown = document.onmousedown; 
			this.origOnMouseUp = document.onmouseup;
			this.origOnMouseMove = document.onmousemove;
			this.origOnMouseOut = document.onmouseout;
			this.origOnMouseDrag = document.onmousedrag;
			this.origOnMouseEnter= document.ondragenter;
			
			document.onmousedown = this.onMouseDown.bind(this) ;
			document.onmouseup = this.onMouseUp.bind(this) ;
			document.onmousemove = this.onMouseMove.bind(this) ;
			document.onmouseout = this.onMouseOut.bind(this) ;
			//document.onmousedrag = this.onMouseDrag.bind(this);
			
		}
		
	},
	
	onDragEnter : function ( e )
	{
		g_log("dragEnter");
		onMouseDown(e);
		//onMouseMove( e );
	},
	
	
	clickTimerCallback : function()
	{
		window.clearTimeout( this.clickTimerId );
		this.clickTimerId = null;
		
		this.checkForDoubleClick = false;
	},
	
	startClickTimer : function()
	{
		if( this.clickTimer != null )
			window.clearTimeout( this.clickTimerId );
		
		this.clickTimerId = window.setTimeout( "g_mouseDevice.clickTimerCallback()", 300 );
		
	},
	
	updateMouseButtonPressedInfo : function(e)
	{
		var clickType=1;
		if (navigator.appName=="Netscape") 
			clickType=e.which;
		else 
		{
			clickType=e.button;
		}
			
			
		this.bLeftMouseButtonPressed = false;
		this.bRightMouseButtonPressed = false;
			
		if( clickType==1 ) 
		{
			//left button
			this.bLeftMouseButtonPressed = true;
		}
  		else if (clickType!=1)
		{ 
		  	//Right button
		  	this.bRightMouseButtonPressed = true;
		}
		
	},
	
	getRightMouseButtonPressed : function()
	{
		return this.bRightMouseButtonPressed;
	},
	
	getLeftMouseButtonPressed : function()
	{
		return this.bLeftMouseButtonPressed;
	},
	
	registerListener : function( listener )
	{	
		
			assert( ArrayGetIndexOf( this.aListeners, listener ) < 0 );
			this.aListeners.push( listener );
	}, 
	
	deregisterListener : function( listener )
	{
	
			assert( ArrayGetIndexOf( this.aListeners, listener ) >= 0 );
			this.aListeners.splice( ArrayGetIndexOf( this.aListeners, listener ),1 );
	},
	
	getMousePosX : function()
	{
		return this.iMousePosX + g_getScrollX() ;
	},
	
	getMousePosY : function()
	{
		return this.iMousePosY + g_getScrollY() ;
	},
	
	getMoveX : function()
	{
		return this.iMoveX;
	},
	
	getMoveY : function()
	{
		return this.iMoveY;
	},
	
	
	onMouseDrag : function( e )
	{		
		if( !e )
			e = window.event;
			
		var bResult = this.mouseMove(e);
		
		if( ! bResult )
		{
			if( this.origOnMouseDrag )
				return this.origOnMouseDrag(e);
		}
		
		return bResult;
	},
	
	onMouseMove : function( e ) 
	{
		if( !e )
			e = window.event;
		
		var bResult = this.mouseMove(e);
		
		if( ! bResult )
		{
			if( this.origOnMouseMove )
				return this.origOnMouseMove(e);
		}
		
		return bResult;
	},
	
	getClientX : function(e)
	{	
		if( this.bIsSafari )
			return e.clientX - g_getScrollX();
		else
			return e.clientX;
	},
	
	getClientY : function(e)
	{
		if( this.bIsSafari )
			return e.clientY - g_getScrollY();
		else
			return e.clientY;
	},
	
	mouseMove : function(e)
	{
		if ( ! e )
			e = window.event ;
			
		//dragging
		this.iMoveX = this.getClientX(e) - this.iMouseLastPosX; 		
		this.iMoveY = this.getClientY(e) - this.iMouseLastPosY;
		
		this.iMouseLastPosX = this.getClientX(e);
		this.iMouseLastPosY = this.getClientY(e);
		
		this.iMousePosX = this.getClientX(e); 		
		this.iMousePosY = this.getClientY(e);
		
		//we dont break at the first event consumation .. eg. utils.dragDrop.js should always get a mouseMove!  
		var bOneConsumed = false;
		for ( var i = 0 ; i < this.aListeners.length ; i ++ )
		{
			if( this.aListeners[i].onMouseMove )
			{
				var bConsumed = this.aListeners[i].onMouseMove(e);
				bOneConsumed = bConsumed || bOneConsumed;
				
			}
		}
		
		if( bOneConsumed )
		{
			e.returnValue = false;
			return false;
		}
		
		e.returnValue = true;
		return true;
	},
	
	
	onMouseDown : function ( e ) 
	{	
		if ( ! e )
			e = window.event ;
			
		this.updateMouseButtonPressedInfo(e);
			
		this.iMouseLastPosX = this.getClientX(e);
		this.iMouseLastPosY = this.getClientY(e);
		
		if ( e.stopPropagation ) 
			e.stopPropagation() ;
			 
		e.cancelBubble = true ;
		
		this.startClickTimer();
		
		for ( var i = 0 ; i < this.aListeners.length ; i ++ )
		{
			if( this.aListeners[i].onMouseDown )
			{
				var bConsumed = this.aListeners[i].onMouseDown(e);
				if( bConsumed )
				{
					e.returnValue = false;
					return false;
				}	 
			}
		}
		
		
		if( this.origOnMouseDown )
			return this.origOnMouseDown(e);
			
		e.returnValue = true;
		return true; 
	},
	
	onMouseUp : function ( e ) 
	{
	//	alert("up");
		if ( ! e )
			e = window.event ;
	
		for ( var i = 0 ; i < this.aListeners.length ; i ++ )
		{
			if( this.aListeners[i].onMouseUp )
				this.aListeners[i].onMouseUp(e);
		}
		
		if( this.clickTimerId != null )
		{
			if( this.checkForDoubleClick )
			{
				var iMouseMoveLimit = 10;
				if( 	Math.abs( this.iCheckDoubleClickPosX - this.getMousePosX() ) < iMouseMoveLimit && 
					Math.abs( this.iCheckDoubleClickPosY - this.getMousePosY() ) < iMouseMoveLimit  
				  )
				{
					this.onMouseDoubleClick(e);
					this.checkForDoubleClick = false;
				}
			}
			else
			{
				//this.startClickTimer();
				this.onMouseClick(e);
				this.checkForDoubleClick = true;
				//remember mousePos
				this.iCheckDoubleClickPosX = this.getMousePosX();
				this.iCheckDoubleClickPosY = this.getMousePosY();
			}
		}
		
		if( this.origOnMouseUp )
			return this.origOnMouseUp(e);
		
		e.returnValue = true;	
		return true;
	},
	
	onMouseDoubleClick : function ( e ) 
	{
		for ( var i = 0 ; i < this.aListeners.length ; i ++ )
		{
			if( this.aListeners[i].onMouseDoubleClick )
				this.aListeners[i].onMouseDoubleClick(e);
		}
		
		//alert("double");
	},
	
	onMouseClick : function ( e ) 
	{
		for ( var i = 0 ; i < this.aListeners.length ; i ++ )
		{
			if( this.aListeners[i].onMouseClick )
				this.aListeners[i].onMouseClick(e);
		}
		
		//alert("click");
	},
	
	onMouseOut : function ( e ) 
	{
		if ( ! e )
			e = window.event ;
	
		for ( var i = 0 ; i < this.aListeners.length ; i ++ )
		{
			if( this.aListeners[i].onMouseOut )
				this.aListeners[i].onMouseOut(e);
		}
		
		if( this.origOnMouseOut )
			return this.origOnMouseOut(e);
			
		return true;
	},
	
	/** Event handler for mouse wheel event.
	 */
	onMouseWheel : function (event)
	{
		var delta = 0;
        if (!event) /* For IE. */
                event = window.event;
        if (event.wheelDelta) { /* IE/Opera. */
                delta = event.wheelDelta/120;
                /** In Opera 9, delta differs in sign as compared to IE.
                 */
                if (window.opera)
                        delta = -delta;
        } else if (event.detail) { /** Mozilla case. */
                /** In Mozilla, sign of delta is different than in IE.
                 * Also, delta is multiple of 3.
                 */
                delta = -event.detail/3;
        }
        /** If delta is nonzero, handle it.
         * Basically, delta is now positive if wheel was scrolled up,
         * and negative, if wheel was scrolled down.
         */
        if (delta)
        {
               for ( var i = 0 ; i < this.aListeners.length ; i ++ )
			{
				if( this.aListeners[i].onMouseWheel )
				{
					var bConsumed = this.aListeners[i].onMouseWheel(delta);
					if( bConsumed )
					{
						event.returnValue = false;
						
						if (event.preventDefault)
                				event.preventDefault();
                
						return false;
					}
				}
			}
        }
        /** Prevent default actions caused by mouse wheel.
         * That might be ugly, but we handle scrolls somehow
         * anyway, so don't bother here..
         */
        
	
	//alert("trur");
		event.returnValue = true;
		return true;
	}


});

if( ! document.mouseDevice )
	document.mouseDevice = new MouseDevice();
	
var g_mouseDevice = document.mouseDevice; 

