(function($) {
	$.fn.SPgallery = function(settings) {
		settings = $.extend({
			layerPreview:		'',
			timeout:			1000,
			imgLoadingSrc:		'/images/loading.gif',
			imgLoadingClass:	'loading',
			thumbHoverClass:	'hover',
			thumbSelectedClass:	'current',
			preloadedImages:	{}
		},settings);
		
		var matchedObj = this;
		var loading = null;
		var timer_timeout = null;
		var timer_interval = null;
		
		function _initialize() {
			_start(this,matchedObj); // This, in this context, refer to object (link) which the user have clicked
			return false; // Avoid the browser following the link
		}
		function _start(objClicked,matchedObj) {
			if( loading )
				return false;
			
			_loading( true );
		
			var thumb_src = $(objClicked).attr('src');
			var prev_src = $(settings.layerPreview +' img:first').attr('src');
			settings.preloadedImages[thumb_src] = true;
			settings.preloadedImages[prev_src] = true;
			
			thumb_src = thumb_src.replace('/images/Thumbnail/', '/images/');
			prev_src = prev_src.replace('/images/', '/images/Thumbnail/');
			
			var thumb_ready = false;
			var prev_ready = false;
			if( ! settings.preloadedImages[thumb_src] ) {
				settings.preloadedImages[thumb_src] = true;
				var thumb = new Image( );
				thumb.onload = function( ) {thumb_ready=true;}
				thumb.src = thumb_src;
			}
			else {
				thumb_ready = true;
			}
			if( ! settings.preloadedImages[prev_src] ) {
				settings.preloadedImages[prev_src] = true;
				var prev = new Image( );
				prev.onload = function( ) {prev_ready=true;}
				prev.src = prev_src;
			}
			else {
				prev_ready = true;
			}
			
			timer_timeout = setTimeout( function(){
				clearInterval(timer_interval);
				timer_interval=false;
				_swap(objClicked, matchedObj, thumb_src, prev_src);
				_loading( false );
				_resetClosures( );
			}, settings.timeout );
			
			timer_interval = setInterval( function(){
				if(thumb_ready&&prev_ready) 
				{
					clearTimeout(timer_timeout);
					clearInterval(timer_interval);
					_swap(objClicked, matchedObj, thumb_src, prev_src);
					_loading( false );
					_resetClosures( );
				} 
			}, 80 );
					
			if( settings.thumbSelectedClass )
			{
				$(matchedObj).removeClass(settings.thumbSelectedClass);
				$(objClicked).addClass(settings.thumbSelectedClass);
			}
		}
		function _swap(objClicked, matchedObj, thumbSrc, previewSrc) {
			$(settings.layerPreview +' img:first').attr('src', thumbSrc);
			$(objClicked).attr('src', previewSrc);
		}
		function _resetClosures( ) {
			loading = timer_timeout = timer_interval = null;
		}
		function _loading( show ) {
			if( ! settings.imgLoadingSrc || ! settings.imgLoadingClass)
				return;
				
			loading = !!show;
			var loadingObj = $(settings.layerPreview +' .' + settings.imgLoadingClass);
			if( show )
				loadingObj.show();
			else
				loadingObj.hide();

		}
		
		$(settings.layerPreview).append('<img src="'+settings.imgLoadingSrc+'" class="'+settings.imgLoadingClass+'" alt="" style="display:none" />');
		if( settings.thumbHoverClass )
			$(matchedObj).hover( function(){ $(this).addClass(settings.thumbHoverClass); }, function(){$(this).removeClass(settings.thumbHoverClass);} );

		return this.unbind('click').click(_initialize);
	};
})(jQuery);