/*
Sky.MouseFollower 
copyright by MySign AG (http://www.mysign.ch), Mike Mueller
depencies: Prototype 1.6
           script.aculo.us 1.8.1 effects
*/
// creating namespace
var Sky;
if ( !Sky ) Sky = {};

Sky.MouseFollower = Class.create();


Sky.MouseFollower.DIRECTION_UP_RIGHT =   'up-right';
Sky.MouseFollower.DIRECTION_DOWN_RIGHT = 'down-right';
Sky.MouseFollower.DIRECTION_UP_LEFT =    'up-left';
Sky.MouseFollower.DIRECTION_DOWN_LEFT =  'down-left';

Sky.MouseFollower._REQUIRED_PROTOTYPE = '1.6.0.2';
Sky.MouseFollower._REQUIRED_SCRIPTACULOUS_EFFECTS = '1.8.1';


Sky.MouseFollower.prototype =
{
	initialize: function( id, opts ) 
	{
		// checking Sky.PrototypeExtensions
		if( Object.isUndefined( Sky.PrototypeExtensions ) )
		{
			throw( "Sky.MouseFollower requires the Sky.PrototypeExtensions JavaScript framework" );
		}
		// checking Prototype
		if( !Sky.PrototypeExtensions.isPrototypeLoaded( Sky.MouseFollower._REQUIRED_PROTOTYPE ) )
		{
			throw( "Sky.MouseFollower requires the Prototype JavaScript framework >= " + Sky.MouseFollower._REQUIRED_PROTOTYPE );
		}
		// checking script.aculo.us effects
		if( !Sky.PrototypeExtensions.isScriptaculousEffectsLoaded( Sky.MouseFollower._REQUIRED_SCRIPTACULOUS_EFFECTS ) )
		{
			throw( "Sky.MouseFollower requires the script.aculo.us effects JavaScript framework >= " + Sky.MouseFollower._REQUIRED_SCRIPTACULOUS_EFFECTS );
		}
		
		this.options = 
		{
			tag:			'div',
			code:			'',
			duration:		1.0,
			stillPosTop:		10,
			stillPosLeft:		10,
			durationFixedForPixels:	0,
			minDistanceToMove:	0,
			transition:		Effect.Transitions.linear
		}
		Object.extend(this.options, opts || {} );
		
		this.lastEffect = null;
		this.idle = true;
		this.idleStartTime = new Date().getTime();
		this.moveStartTime = 0;
		this.onmousemoveBindListener = this._onmousemove.bindAsEventListener( this );
		
		Event.observe( document, 'mousemove', this.onmousemoveBindListener ); 
		$( document.body ).insert( { bottom: '<' + this.options.tag + ' id="' + id + '">' + this.options.code + '</' + this.options.tag + '>' } );
		this.follower = $(id);
		this.follower.absolutize();
		//this.follower.setStyle( { top: '0', left: '0' } );
	},
	
	isIdle: function ()
	{
		return this.idle;
	},
	
	getMovingTime: function ()
	{
		var returnValue = 0;
		
		if ( !this.isIdle() )
		{
			returnValue = new Date().getTime() - this.moveStartTime
		}
		
		return returnValue;
	},

	getIdleTime: function ()
	{
		var returnValue = 0;
		
		if ( this.isIdle() )
		{
			returnValue = new Date().getTime() - this.idleStartTime
		}
		
		return returnValue;
	},
	
	stop: function ()
	{
		Event.stopObserving( document, 'mousemove', this.onmousemoveBindListener ); 
		if ( this.lastEffect != null )
		{
			var pos = this.follower.cumulativeOffset();
			this.lastEffect.cancel();
			this.lastEffect = null;
			this.follower.setStyle( { top: pos.top.toString() + 'px', left: pos.left.toString() + 'px' } );
		}
		this._afterFinishMove( this.lastEffect );
	},

	_afterFinishMove: function ( effect )
	{
		if ( this.lastEffect == effect )
		{
			this.lastEffect = null;
			this.idle = true;
			this.idleStartTime = new Date().getTime();
			this.follower.fire( 'MouseFollower:idle' );
		}
	},
	
	_onmousemove: function ( event )
	{
		var createNewEffect = true;
		
		var pointerX = Event.pointerX(event);
		var pointerY = Event.pointerY(event);
		var pos = this.follower.cumulativeOffset();
		
		var posLeft = pos.left - this.options.minDistanceToMove;
		var posTop = pos.top - this.options.minDistanceToMove;
		var posRight = posLeft + this.options.minDistanceToMove + this.follower.getWidth() + this.options.minDistanceToMove;
		var posBottom = posTop + this.options.minDistanceToMove + this.follower.getHeight() + this.options.minDistanceToMove;
		
		var canMove = ( pointerX < posLeft || pointerX > posRight || pointerY < posTop || pointerY > posBottom );
		
		if ( this.lastEffect != null )
		{
			if ( this.lastEffect.currentFrame < 5 )
			{
				createNewEffect = false;
			}
			else
			{
				this.lastEffect.cancel();
				if ( !canMove )
				{
					this._afterFinishMove( this.lastEffect );
				}
				this.lastEffect = null;
				this.follower.setStyle( { top: pos.top.toString() + 'px', left: pos.left.toString() + 'px' } );
			}
		}
		if ( createNewEffect )
		{
			if ( canMove )
			{
				if ( pos.left - ( pointerX + this.options.stillPosLeft ) < 0 )
				{
					if ( pos.top - ( pointerY + this.options.stillPosTop ) > 0 )
					{
						this.follower.fire( 'MouseFollower:newmove', { direction: Sky.MouseFollower.DIRECTION_UP_RIGHT } );
					}
					else
					{
						this.follower.fire( 'MouseFollower:newmove', { direction: Sky.MouseFollower.DIRECTION_DOWN_RIGHT } );
					}
				}
				else
				{
					if ( pos.top - ( pointerY + this.options.stillPosTop ) > 0 )
					{
						this.follower.fire( 'MouseFollower:newmove', { direction: Sky.MouseFollower.DIRECTION_UP_LEFT } );
					}
					else
					{
						this.follower.fire( 'MouseFollower:newmove', { direction: Sky.MouseFollower.DIRECTION_DOWN_LEFT } );
					}
				}
				var duration = this.options.duration;
				var dist = Math.round( Math.sqrt( Math.pow( Math.abs( pos.top - pointerY - this.options.stillPosTop ), 2 ) + Math.pow( Math.abs( pos.left - pointerX - this.options.stillPosLeft ), 2 ) ) )
				if ( this.options.durationFixedForPixels > 0 )
				{
					duration = duration * ( dist / this.options.durationFixedForPixels );
				}
				//$('debug').update( 'duration: ' + duration + ', dist: ' + dist + ', yDist: ' + Math.abs( pos.top - pointerY - this.options.stillPosTop ) + ', xDist: ' + Math.abs( pos.left - pointerX - this.options.stillPosLeft ) );
				this.lastEffect = new Effect.Move( this.follower, 
							      { x: pointerX + this.options.stillPosLeft, 
								y: pointerY + this.options.stillPosTop, 
								mode: 'absolute', 
								duration: duration,
								afterFinish: this._afterFinishMove.bind( this ),
								transition: this.options.transition
							      } );
				if ( this.idle )
				{
					this.moveStartTime = new Date().getTime();
				}
				this.idle = false;	
			}
		}
	}
}

// For compatibility reasons
var My;
if( !My ) My = {};
My.MouseFollower = Sky.MouseFollower;