(function($) {

$.fn.imageGallery = function(options) {
	var defaults = {
		width: 'auto',
		height: 'auto',
		itemSelector: '.galleryItem',
		nextPrevButtons: false,
		itemButtons: false,
		transition: 'opacity',
		transspeed: '1000',
		speed: '5000',
		autoplay: true
	}
	var o = $.extend(defaults, options);
	var itemIndex = -1;
	var waitingIndex = -1;
	var reverse = false;
	
	return this.each(function() {
		var g = $(this);
		var gi = g.find(o.itemSelector);
		gi.find('img').load(function() {
			ti = $(this);
			ti.attr('loaded',true);
			if(waitingIndex == ti.parents(o.itemSelector).attr('index')) {
				g.find('.loading').remove();
				waitingIndex = -1;
				transitionIn(ti.attr('index'));
			}
		}).each(function(index) {
			var ti = $(this)
			ti.attr('index',index);
			ti.parents(o.itemSelector).attr('index',index);
			if(ti.attr('complete') || ti.attr('readyState') == 4 || ti.height() > 20) {
				ti.attr('loaded',true);
			}
		});
		var playing = o.autoplay;
		var playTimer;
		g.css({
			'position':'relative',
			'overflow':'hidden'
		});
		gi.css( { 
			'position':'absolute',
			'top':'0px',
			'left':'0px',
			'width':'100%',
			'height':'100%'
		}).hide();
		
		g.append('<div class="transitionLayer"></div>');
		tl = g.children('.transitionLayer').css({
			'position':'absolute',
			'display':'none',
			'top':'0px',
			'left':'0px',
			'width':'100%',
			'height':'100%',
			'z-index':3
		});
		
		if(o.width != 'auto') {
			g.width(o.width);
		}
		if(o.height != 'auto') {
			g.height(o.height);
		}
		
		if(o.nextPrevButtons) {
			g.append('<div class="leftButton"></div><div class="rightButton"></div>');
			g.children('.leftButton').click(function(){
				playing = false;
				clearTimeout(playTimer);
				reverse = true;
				transitionIn(itemIndex-2);
			});
			g.children('.rightButton').click(function(){
				playing = false;
				clearTimeout(playTimer);
				transitionIn();
			});
		}
		
		if(o.itemButtons) {
			g.append('<div class="itemButtons"></div>');
			ib = g.children('.itemButtons');
			gi.each(function(i) {
				thisgi = $(this);
				if(thisgi.find('img:first').attr('data-thumb')) {
					ib.append('<div class="itemButton thumbnailButton" data-index="'+i+'"><img src="'+thisgi.find('img:first').attr('data-thumb')+'" alt="" /></div>');
				} else {
					ib.append('<div class="itemButton" data-index="'+i+'"></div>');
				}
				var nb = ib.children('.itemButton[data-index='+i+']');
				nb.click(function(e) {
					playing = false;
					clearTimeout(playTimer);
					ti = $(this);
					if(itemIndex > ti.attr('data-index')) {
						reverse = true;
					}
					ti.siblings().removeClass('activeButton');
					ti.addClass('activeButton');
					transitionIn(parseInt(ti.attr('data-index')));
					e.stopPropagation();
				});
			});
		}
		
		transitionIn(0);
		
		function transitionIn(i) {
			var lastIndex = itemIndex;
			if(!isNaN(i)) {
				itemIndex = parseInt(i);
			} else {
				itemIndex++;
			}
			
			if(itemIndex < 0) {
				itemIndex += gi.length;
			} else if(itemIndex > gi.length - 1) {
				itemIndex -= gi.length;
			}
			
			var ni = gi.slice(itemIndex,itemIndex+1);
			var li = gi.slice(lastIndex,lastIndex+1);
			
			if((ni.find('img').attr('loaded')||ni.find('img').attr('readyState') == "complete") && !ni.is(':animated') && !li.is(':animated') && !tl.children().is(':animated')) {
				if(li.html() != ni.html()) {
					ni.addClass('activeItem');
					li.removeClass('activeItem');
					ni.css('z-index',5);
					li.css('z-index',1);
					
					var transition = ni.attr('data-transition') || o.transition;
					var dl =  ni.attr('data-display-length') || o.speed;
					
					if(playing) {
						playTimer = setTimeout( function() {
							transitionIn();
						},dl)
					}
					if(reverse) {
						switch(transition) {
							case 'right':
								transition = "left";
								break;
							case 'left':
								transition = "right";
								break;
							case 'top':
								transition = "bottom";
								break;
							case 'bottom':
								transition = "top";
								break;
						}
						reverse = false;
					}
					switch(transition) {
						case 'right':
							if(li.css('display') == 'block') {
								ni.css('left',"-" + ni.width() +"px").show();
								ni.animate({ left:"0px" },o.transspeed);
								li.animate({ left:ni.width()+"px" },o.transspeed);
							} else {
								ni.show();
							}
							break;
						case 'left':
							if(li.css('display') == 'block') {
								ni.css('left',ni.width() +"px").show();
								ni.animate({ left:"0px" },o.transspeed);
								li.animate({ left:"-" + ni.width()+"px" },o.transspeed);
							} else {
								ni.show();
							}
							break;
						case 'top':
							if(li.css('display') == 'block') {
								ni.css('top',"-" + ni.height() +"px").show();
								ni.animate({ top:"0px" },o.transspeed);
								li.animate({ top:ni.height()+"px" },o.transspeed);
							} else {
								ni.show();
							}
							break;
						case 'bottom':
							if(li.css('display') == 'block') {
								ni.css('top',ni.height() +"px").show();
								ni.animate({ top:"0px" },o.transspeed);
								li.animate({ top:"-" + ni.height()+"px" },o.transspeed);
							} else {
								ni.show();
							}
							break;
						case 'checkerboard':
							var img = ni.find('img');
							ni.show();
							var sizeX = Math.ceil(ni.width()/10);
							var sizeY = Math.ceil(ni.height()/8);
							img.hide();
							tl.html('');
							for (x = 0; x < 10; x++) {
								for (y = 0; y < 8; y++) {
									$("<div />").css({
										width: sizeX,
										height: sizeY,
										left: x * sizeX,
										top: y * sizeY,
										backgroundPosition: "-" + x * sizeX + "px -" + y * sizeY + "px",
										position:'absolute',
										display:'none',
										'background-image': 'url(' +img.attr('src') +')'
									}).appendTo(tl);
								}
							}
							tl.show().children().each( function(a,i) {
								$(this).delay(Math.random() * (o.transspeed*0.75)).fadeIn(o.transspeed/4,function() {
									var tb = $(this);
									if(tb.siblings().length == tb.siblings(':visible:not(:animated)').length) {
										tb.parent().siblings('.activeItem').find('img').show();
										tl.hide();
									}
								});
							});
							break;
						case 'joinV':
							var img = ni.find('img');
							ni.show();
							var sizeX = Math.ceil(ni.width() + (ni.width()/2));
							var sizeY = Math.ceil(ni.height());
							img.hide();
							tl.html('');
							for (x = 0; x < 2; x++) {
								$("<div />").css({
									width: (ni.width()/2),
									height: sizeY,
									left: x * sizeX - (ni.width()/2),
									top: 0,
									backgroundPosition: "-" + (x * sizeX) + "px 0px",
									position:'absolute',
									'background-image': 'url(' +img.attr('src') +')'
								}).appendTo(tl);
							}
							tl.show().children(':eq(0)').animate({left:0 + "px"},o.transspeed).siblings('div').animate({left:ni.width()/2 + "px"},o.transspeed, function() {
								var tb = $(this);
								tb.parent().siblings('.activeItem').find('img').show();
								tl.hide();
							});
							break;
						case 'joinH':
							var img = ni.find('img');
							ni.show();
							var sizeX = Math.ceil(ni.width());
							var sizeY = Math.ceil(ni.height() + (ni.height()/2));
							img.hide();
							tl.html('');
							for (y = 0; y < 2; y++) {
								$("<div />").css({
									width: sizeX,
									height: (ni.height()/2),
									left: 0,
									top: y * sizeY - (ni.height()/2),
									backgroundPosition: "-0px " + (y * sizeY) + "px",
									position:'absolute',
									'background-image': 'url(' +img.attr('src') +')'
								}).appendTo(tl);
							}
							tl.show().children(':eq(0)').animate({top:0 + "px"},o.transspeed).siblings('div').animate({top:ni.height()/2 + "px"},o.transspeed, function() {
								var tb = $(this);
								tb.parent().siblings('.activeItem').find('img').show();
								tl.hide();
							});
							break;
						case 'splitV':
							li.css('z-index',5);
							ni.css('z-index',1);
							var img = li.find('img');
							li.show();
							ni.show();
							var sizeX = Math.ceil(li.width()/2);
							var sizeY = Math.ceil(li.height());
							img.hide();
							tl.html('');
							for (x = 0; x < 2; x++) {
								$("<div />").css({
									width: sizeX,
									height: sizeY,
									left: x * sizeX,
									top: 0,
									backgroundPosition: "-" + (x * sizeX) + "px 0px",
									position:'absolute',
									'background-image': 'url(' +img.attr('src') +')'
								}).appendTo(tl);
							}
							tl.show().children(':eq(0)').animate({left:-sizeX + "px"},o.transspeed).siblings('div').animate({left:li.width() + "px"},o.transspeed, function() {
								var tb = $(this);
								tb.parent().siblings(o.itemSelector).css('z-index',1).hide().find('img').show();
								tb.parent().siblings('.activeItem').css('z-index',5).show();
								tl.hide();
							});
							break;
						case 'splitH':
							li.css('z-index',5);
							ni.css('z-index',1);
							var img = li.find('img');
							li.show();
							ni.show();
							var sizeX = Math.ceil(li.width());
							var sizeY = Math.ceil(li.height()/2);
							img.hide();
							tl.html('');
							for (y = 0; y < 2; y++) {
								$("<div />").css({
									width: sizeX,
									height: sizeY,
									left: 0,
									top: y * sizeY,
									backgroundPosition: "0px -" + (y * sizeY) + "px",
									position:'absolute',
									'background-image': 'url(' +img.attr('src') +')'
								}).appendTo(tl);
							}
							tl.show().children(':eq(0)').animate({top:-sizeY + "px"},o.transspeed).siblings('div').animate({top:li.height() + "px"},o.transspeed, function() {
								var tb = $(this);
								tb.parent().siblings(o.itemSelector).css('z-index',1).hide().find('img').show();
								tb.parent().siblings('.activeItem').css('z-index',5).show();
								tl.hide();
							});
							break;
						case 'opacity':
						default:
							ni.css('left','0px').hide().fadeIn(o.transspeed, function() {
								$(this).siblings(o.itemSelector).hide();
							});
							break;
					}
					if(o.itemButtons) {
						g.find('.itemButton').removeClass('activeButton');
						g.find('.itemButton[data-index="'+ni.attr('index')+'"]').addClass('activeButton');
					}
				}
			} else {
				if(!ni.is(':animated') && !li.is(':animated')) {
					waitingIndex = itemIndex;
					g.prepend('<div class="loading"></div>');
				}
				if(!isNaN(i)) {
					itemIndex = lastIndex;
				}
			}
		}
	});
};
}) ($)
