(function($) {
	
	$.fn.extend({
		
		preloadImages : function(options) {
			
			// Settings
			var defaults = {
								
				debugLevel : 2, // 0 = off, 1 = error, 2 = warning, 3 = message
				
				delay : 0, // how long to wait (in ms) between loading each image
				
				onFirstImageLoad : function() {
					$(document).trigger('firstImageLoaded');
					log('First image loaded');
				},
								
				onEachImageLoad : function() {
					var currentImage = $(this);
					var id = currentImage.data('id');
					currentImage.data('loaded', 'true');
					if (id) log('Image ' + id + ' loaded');
				},
				
				onLoadingComplete : function() {
					log('All images loaded');
				}
				
			};
			var settings = $.extend({}, defaults, options);
			
			// Preload images
			return this.each(function() {
				var images = $(this).find('img');
				var prevId = 0;
				var firstImageLoaded = false;
				var t = null;
				
				images.bind('show', function() {
					var img = $(this);
					var src = img.data('src');
					var id = parseInt(img.data('id'));
					var nextImg = $(images[id]);
		    	
					if (src) {
						if (id) {
							if (img.data('loaded')) {
								log('Image ' + id + ' already loaded, skipping image', 3);
								showImage(nextImg, id);
							} else {
								img.load(function() {
									showImage(nextImg, id);
									settings.onEachImageLoad.call(this);
									if (!firstImageLoaded) {
										firstImageLoaded = true;
										settings.onFirstImageLoad.call(this);
									}
									if (!nextImg.length) {
										settings.onLoadingComplete.call(this);
									}
								});
								img.attr('src', src);
							}
						} else {
							log('No data-id attribute found, skipping image', 1);
						}
					} else {
						log('No data-src attribute found, skipping image', 1);
						showImage(nextImg, id);
					}
				});
				
				function showImage(img, id) {
					if (t) {
						clearTimeout(t);
					}
					t = setTimeout(function() {
						if (id == prevId + 1) {
							prevId = id;
						} else {
							img = $(images[prevId]);
						}
						img.trigger('show');
					}, settings.delay);
				}
				
				images.first().trigger('show');
			});
			
			function log(message, debugLevel) {
				// if no level is specified, assume it's a message (level 3)
				var level = (debugLevel) ? debugLevel : 3;
				if (level <= settings.debugLevel) {
					if (window.console) console.log(message);
				}
			}
		}
	});
})(jQuery);
