/**
 * 
 * jQuery.cursorSpinner (c) 2008 Daniel Smedegaard Buus (daniel@arkena.dk) 
 * 
 * Cursor waiting spinner functions. Will display a transparent spinner graphics
 * next to the mouse cursor for five seconds after attachCursorSpinner() has been
 * called, or until removeCursorSpinner() is called.
 *  
 * WARNING: Know how to use unbind! Name what you unbind, or you will unbind the mouse tracker!
 * 
 * I.e.:
 * 
 * BAD:		$().unbind('mousemove');				// This unbinds ALL listeners.
 * GOOD:	$().unbind('mousemove', yourListener);	// This unbinds yourListener ONLY.
 * 
 */


jQuery.attachCursorSpinner = function()
{
	// You must initialize the cursor spinner using $.initCursorSpinner before this method is implemented.
}


jQuery.removeCursorSpinner = function()
{
	// You must initialize the cursor spinner using $.initCursorSpinner before this method is implemented.
}

// TODO: This name suxxorss. Something like animatedCursorTag better describes what this is about.
// TODO: We can change the cursor, too, if we use $('clicked_element').css('cursor', 'wait'). We'd probably want to collect the element name at init (or at attach). 
jQuery.initCursorSpinner = function(args)
{
	try {
		var image_src		= typeof(args.image_src)		!=	 'undefined' ? args.image_src		: 'jquery_cursor_spinner.png';
		var image_width		= typeof(args.image_width)		!=	 'undefined' ? args.image_width		: 176;
		var image_height	= typeof(args.image_height)		!=	 'undefined' ? args.image_height	: 16;
		var ticks			= typeof(args.ticks)			!=	 'undefined' ? args.ticks			: image_width/image_height; // Assume square spinner, thus the width should be a multiple of the height
		var frequency		= typeof(args.frequency)		!=	 'undefined' ? args.frequency		: 100;
		var offset_left		= typeof(args.offset_left)		!=	 'undefined' ? args.offset_left		: -1*((image_width/ticks)-2);
		var offset_top		= typeof(args.offset_top)		!=	 'undefined' ? args.offset_top		: image_height-2;
		var timeout			= typeof(args.timeout)			!=	 'undefined' ? args.timeout			: 4000;
	} catch(e) { return $.initCursorSpinner({}) };
	
	var tick = 0;
	var anim_interval_handle = null;
	var auto_removal_timeout_handle = null;
	var spinning = false;
	
	// Until we get a reading on the mouse position, make sure we render any dislocated spinner outside the browser frame until we get a reading:
	var last_mouse_x = 10;
	var last_mouse_y = 10;
	
	// Track mouse movements:
	$().mousemove(trackMouse = function(e) { last_mouse_x = e.pageX; last_mouse_y = e.pageY; });
	
	
	var moveSpinner = function(e)
	{
		$('#jqc_spinner').css('left', e.pageX+offset_left);
		$('#jqc_spinner').css('top', e.pageY+offset_top);
	}
	
	
	var updateAnimation = function()
	{
		// Only while we're spinning:
		if (spinning)
		{
			// Position background image in the spinner image div to reveal the appropriate frame:
			$('#jqc_spinner_frames').css('left', -1*(image_width/ticks)*tick);
			// Update tick:
			tick = (tick % (ticks-1))+1;
		}
	}
	
	
	var cleanUp = function()
	{
		// Unbind the onmousemove event listener:
		$().unbind('mousemove', moveSpinner);
		
		// Remove the spinner element, clear vars and interval:
		$('#jqc_spinner').remove();
		spinning = false;
		clearTimeout(anim_interval_handle);
	}
	
	
	jQuery.attachCursorSpinner = function()
	{
		// Safety first, people. Some browsers (IE) don't like it when we insert elements into the DOM while they're loading, and yet they're not capable of preventing us in doing so. So wait until the DOM is ready:
		$(document).ready(function() {
			// We only attach once...:
			if (!spinning)
			{
				spinning = true;
				
				// Inject the elements into the DOM. Use PNG filter for old IE browsers: 
				var background_style = ($.browser.msie && parseInt($.browser.version)<7) ? "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image_src+"');" : "background:url("+image_src+") no-repeat top left;";
				$('body').append('<div id="jqc_spinner" style="z-index:0;position:absolute;width:16px;height:16px;overflow:hidden;"><div id="jqc_spinner_frames" style="position:relative;width:176px;height:16px;top:0px;left:0px;'+background_style+'"></div></div>');
				
				// Position the spinner by the mouse:
				moveSpinner({ pageX:last_mouse_x, pageY:last_mouse_y });
				
				// Continue doing so on every mouse movement:
				$().mousemove(moveSpinner);
				
				// Start animation
				anim_interval_handle = setInterval(updateAnimation, frequency);
			}
			else
			{
				// ...but we reset the automatic removal timer when we're called again while spinning:
				clearTimeout(auto_removal_timeout_handle);
			}
			
			// (Re-)schedule automatic removal upon timeout:
			auto_removal_timeout_handle = setTimeout('$.removeCursorSpinner()', timeout);
		});
	}
	
	
	jQuery.removeCursorSpinner = function()
	{
		// Clear the automatic removal timeout:
		clearTimeout(auto_removal_timeout_handle);
		
		// Remove the element from the DOM. Fading a div with a filtered PNG background crashes IE6, so we only fade on real browsers:
		if ($.browser.msie && parseInt($.browser.version)<7)
			cleanUp();
		else
			$('#jqc_spinner').fadeOut(1000, function() { cleanUp(); });
	}
}
