(function($) {
	//If the UI scope is not availalable, add it
	$.ui = $.ui || {};	
	$.fn.loader = function(options) {
		var defaults = {
					text: 'loading....',
					align: 'center',
					valign:'center',
					top: null,
					left: null,
					errormsg: 'Failed to load url.<br />Please check that the url is valid and your have not lost connection.',
					retries:3,
					timeout:5000,
					onSuccess:null,
					onError: null,
					dataType: "text",
					onLoad: null,
					autoLoad : true,
					insertType: 'html',
					loadertpl:'<div class="loader" id="loader" name="loader"><span class="loader-icon"></span>%s</div>'
				};

		options = $.extend({},defaults, options);

		return $.extend(this.each(function() {
								$.extend($.fn.loader.control,new $.ui.loader(this,options));
							}),$.fn.loader.control);

	}
	
	$.fn.loader.globalurlretry = null; // this is for setting global url retry , it stores the last url timeout retry incase you create a new object you would want to cancel the previous retries if any

	$.fn.loader.control = {
			load: function(url,params,onSuccess,onError,onLoad)
			{
				
					this.cancel();
					this.options.url = url || false;
					this.options.params = params || {};
					this.options.onSuccess = onSuccess || this.options.onSuccess;
					this.options.onError = onError || this.options.onError;
					this.options.onLoad = onLoad || this.options.onLoad;	
					this.options.retriesLeft = this.options.retries;
					this.init();	
					if(this.options.url != false)
					{
						
						var ajaxError = function(request)
										{
												
												this.loader.cancel();								
												if(this.loader.options.retriesLeft > 0)
												{
													this.loader.options.retriesLeft--;
													ajaxOptions = this;
													this.loader.urlretry = setTimeout(
																					  function(opts)
																					  {
																						 $.ajax(opts); 
																					  },this.loader.options.timeout,ajaxOptions);
													$.fn.loader.globalurlretry = this.loader.urlretry;
												}														
												
												if(typeof(this.loader.options.onError) == 'function'){
													this.loader.options.onError({
														message : this.loader.options.errormsg,
														retries :this.loader.options.retries,
														retryAttempt   : (this.loader.options.retries - this.loader.options.retriesLeft),
														url		: this.url,
														statusText: request.statusText,
														status : request.status,
														timeout: this.loader.options.timeout
													});	
												}							
										};							
						
						var ajaxSuccess =  function(response)
											{
												if(typeof(this.loader.options.onLoad) == 'function')
												{
													this.loader.options.onLoad(response,this);
												}
													
													this.loader.cancel();
													if(this.loader.options.autoLoad)
													{													
														this.loader.html(response);
													}
													
													if(typeof(this.loader.options.onSuccess) == 'function')
													{
														this.loader.options.onSuccess(response,this);
													}
											};					
						
						$.ajax({ url: this.options.url,
								   data: this.options.params,
								   type: "POST",						   
								   dataType: this.options.dataType,
								   success: ajaxSuccess,
								   error: ajaxError,
								   global: false,
								   loader: this
							   });					
					}
					
			},
			cancel: function()
			{
				if(this.urlretry != null)
				{
					clearTimeout(this.urlretry);
					this.urlretry = null;									
				}	
				if($.fn.loader.globalurlretry != null)
				{
					clearTimeout($.fn.loader.globalurlretry);
					$.fn.loader.globalurlretry = null;									
				}
			},
			html: function(content)
			{	
				var el = $(this.element);
				switch(this.options.insertType.toLowerCase())
				{
					case 'replace':	this.element =el.after(content)
					  				.next();
									el.remove();
					break;
					case 'after':
					case 'before':eval('el.'+this.options.insertType.toLowerCase()+'(content)');
								  el.empty();
					break;
					default: eval('el.'+this.options.insertType.toLowerCase()+'(content)');					
				}				
			}
	}
	
	
	$.ui.loader = function(el,objOptions)
	{
					if(!objOptions) var objOptions = {};
					this.element = el;
					this.options = {};
					$.extend(this.options, objOptions);					
	}


	$.extend($.ui.loader.prototype, {
		init: function()
		{
				var loadertpl = this.options.loadertpl.replace('%s',this.options.text);
				$(this.element).html(loadertpl);
				this.loaderEl = $('#loader',this.element);
				this.position();
		},
		position: function()
		{			
			var elW = $(this.element).width();
			var elH = $(this.element).height();
			
			loaderW = this.loaderEl.width();
			loaderH = this.loaderEl.height();
			
			if(loaderW == 0){
				loaderW = $(this.element).width();
			}
			if(loaderH == 0){
				loaderH = $(this.element).height();
			}
			
			if(this.options.align != null)
			{
				switch(this.options.align.toLowerCase())
				{
					case 'left'	 : this.loaderEl.css('margin-left','0px');
						break;
					case 'center': this.loaderEl.css('margin-left',Math.ceil(elW/2 - loaderW/2)+'px');
						break;
					case 'right' :this.loaderEl.css('margin-left',(elW - loaderW)+'px' );
						break;
				}
			}
			if(this.options.valign != null)
			{
				switch(this.options.valign.toLowerCase())
				{
					case 'top'	 : this.loaderEl.css('margin-top','0px');
						break;
					case 'center': this.loaderEl.css('margin-top',Math.ceil(elH/2 - loaderH/2)+'px');
						break;
					case 'bottom' :this.loaderEl.css('margin-top',(elH - loaderH)+'px' );
						break;
				}
			}
			
			if(this.options.top != null)
			{
				 this.loaderEl.css('margin-top',this.options.top);
			}
			if(this.options.left != null)
			{
				 this.loaderEl.css('margin-left',this.options.left);
			}
		}
	});

})(jQuery);