jQuery.iFdGallery = {
	build : function(userOptions){
		var defaults = {
			showCaptions: true,
			slideEnabled: true,
			autoPlay: false,
			showNavigation: true,
			slideSpeed: 5000,
			thumbWidth: 50,
			thumbHeight: 50,
			thumbs: 5,
			width:360,
			height:270,
			buttonsText: { play: "", stop: "", previous: "Précédente", next: "Suivante" },
			leftButtonInner: "-",
			leftButtonCss: {},
			rightButtonInner: "+",
			rightButtonCss: {},
			delayCaption: true,
			userThumbs: false
		};

		return jQuery(this).each(
			function(){
				var thumbsPadding = 0;
				var thumbsBorder = 1;
				var thumbsMargin = 2;
				var thumbsOffsetInner = thumbsBorder * 2 + thumbsPadding * 2;
				var thumbsOffsetOuter = thumbsOffsetInner + thumbsMargin * 2;
				
				var imagePadding = 0;
				var imageBorder = 1;
				var imageOffsetInner = imageBorder * 2 + imagePadding * 2;
				
				//Bring in options
				var options = jQuery.extend(defaults, userOptions);
				
				//Grab our images
				var thumbsList = jQuery(this).children('ul');
				var images = thumbsList.children('li').children('img');
				
				//Calculate how many images we have
				var nbImages = images.size();
				(nbImages >= options.thumbs) ? null : options.thumbs = nbImages;
				
				//Set the initial position
				var pos = 0;
				
				//Hide the images so the user doesn't see crap
				images.fadeOut(1);
				
				//Set the thumbs list
				images.each(function(i){
					jQuery(this).bind("load", function(){
						//Delete hidden image to clean up things
						jQuery(this).prev().remove();
						images = jQuery(this).parents('ul').find('img');
						
						//Set the thumb size
						jQuery(this).width(options.thumbWidth + "px").height(options.thumbHeight + "px");
						jQuery(this).css({
							position:"relative",
							width: options.thumbWidth + "px",
							height: options.thumbHeight + "px"
						});	 	 

						//Set the thumb hover state
						jQuery(this).hover(
							function(){
								jQuery(this).fadeTo(250,1);
							},
							function(){
								if(!jQuery(this).hasClass("fdGallery_selected")){
									jQuery(this).fadeTo(250,0.4);
								}
							}					
						);
						
						//Set the thumb default opacity
						jQuery(this).fadeTo(250,0.4);	
						
						//Set the thumb id
						jQuery(this).attr("id","image-"+i);
						
						//Trigger a click event on the first image
						if(jQuery(this).hasClass('fdGallery_first')){
							jQuery(this).trigger("click",["auto"]);
						}
					});
				
					//Clone so the on loads will fire correctly
					var newImage = jQuery(this).clone(true).insertAfter(this);
					jQuery(this).hide();
	
					//Reset images to the clones
					images = thumbsList.children('li').children('img');
				});
				
				thumbsList.width((options.thumbWidth + thumbsOffsetOuter) * nbImages + "px");
				thumbsList.css({
					width: (options.thumbWidth + thumbsOffsetOuter) * nbImages + "px"
				});
				
				thumbsList.wrap("<div class='fdGallery_thumbs_viewer'></div>");
				
				var thumbsViewer = thumbsList.parent('div');
				thumbsViewer.height(options.thumbHeight + thumbsOffsetOuter + "px").width((options.thumbWidth + thumbsOffsetOuter) * options.thumbs + "px");
				thumbsViewer.css({
					height: options.thumbHeight + thumbsOffsetOuter + "px",
					width: (options.thumbWidth + thumbsOffsetOuter) * options.thumbs + "px"
				});
				
				thumbsViewer.wrap("<div class='fdGallery_thumbs'></div>");
				var thumbsContainer = thumbsViewer.parent('div');
				
				thumbsViewer.before("<span class='fdGallery_thumbs_nav_left'></span>");
				var thumbNavLeftDiv = jQuery(this).find(".fdGallery_thumbs_nav_left");
				thumbNavLeftDiv.html("<a>" + options.leftButtonInner + "</a>");
				var thumbNavLeftAnchor = thumbNavLeftDiv.children("a:first");
				thumbNavLeftDiv.css(options.leftButtonCss);
				
				thumbsViewer.after("<span class='fdGallery_thumbs_nav_right'></span>");
				var thumbNavRightDiv = jQuery(this).find(".fdGallery_thumbs_nav_right");
				thumbNavRightDiv.html("<a>" + options.rightButtonInner + "</a>");
				var thumbNavRightAnchor = thumbNavRightDiv.children("a:first");
				thumbNavRightDiv.css(options.rightButtonCss);
				
				updateThumbsNav();
	
				//Set the container size
				jQuery(this).width(options.width + imageOffsetInner);
				jQuery(this).css({
					width: options.width + imageOffsetInner
				}); 

				//Start building structure
				jQuery(this).prepend("<div class='fdGallery_main'></div>");
				var mainDiv = jQuery(this).find(".fdGallery_main");
				
				//Set the main div size
				mainDiv.width(options.width + imageOffsetInner).height(options.height + imageOffsetInner);
				mainDiv.css({
					width: options.width + imageOffsetInner,
					height: options.height + imageOffsetInner
				}); 
				
				//Add in slideshow elements when appropriate
				if(options.slideEnabled){
					mainDiv.append("<div class='fdGallery_play'></div>");
					var playDiv = mainDiv.children(".fdGallery_play");
					playDiv.html("<a class='fdGallery_play_button'></a><a class='fdGallery_stop_button'></a>");
					playDiv.fadeOut(1);
					var playAnchor = playDiv.children('a:first');
					var stopAnchor = playDiv.children('a:last');
				}
				
				//This div is used to make image and caption fade together
				mainDiv.append("<div class='fdGallery_subdiv'></div>");
				var subDiv = mainDiv.children(".fdGallery_subdiv");
				
				//Set the sub div size
				subDiv.width(options.width).height(options.height);
				subDiv.css({
					width: options.width,
					height: options.height
				});
				
				subDiv.append("<img class='fdGallery_back_img' /><img class='fdGallery_main_img' />");
				var mainImg = subDiv.children("img:last");
				var backImg = subDiv.children("img:first");
				
				mainImg.width(options.width).height(options.height);
				mainImg.css({
					width: options.width,
					height: options.height
				})
				
				//Build custom overlays.
				subDiv.append("<div class='fdGallery_prev_hover'></div><div class='fdGallery_next_hover'></div>");
				var prevHoverDiv = subDiv.find('.fdGallery_prev_hover');
				prevHoverDiv.hide();
				var nextHoverDiv = subDiv.find('.fdGallery_next_hover');
				nextHoverDiv.hide();
				
				//Create the caption div when appropriate
				if(options.showCaptions){
					mainDiv.append("<div class='fdGallery_caption'></div>");
					var captionDiv = mainDiv.children(".fdGallery_caption");
					
					var offset = parseInt(captionDiv.css("padding-left").replace('px','')) + parseInt(captionDiv.css("padding-right").replace('px',''));
	
					captionDiv.width(options.width - offset);
					captionDiv.css({
						width: options.width - offset
					});
				}
				
				//Navigation div 		
				jQuery(this).append("<div class='fdGallery_navigation'></div>");
				var navigationDiv = jQuery(this).find(".fdGallery_navigation");
				navigationDiv.prepend("<a>" + options.buttonsText.previous + "</a> :: <a>" + options.buttonsText.next + "</a>");
				var previousImageAnchor = navigationDiv.children('a:first');
				var nextImageAnchor = navigationDiv.children('a:last');
				
				//Hide the navigation if the user doesn't want it
				if(!options.showNavigation){
					navigationDiv.hide();
				}
				
				//Playing triggers the loop for the slideshow
				var playing = options.autoPlay;
				
				//Create the image link container
				mainImg.wrap("<a></a>");
				var mainLink = mainImg.parent("a");
				
			function activate(){
				//Image click is controls the fading
				images.bind("click",imageClick);
				
				//Hiding refrence to slide elements if slide is disabled
				if(options.slideEnabled){
					if(options.autoPlay){
						playing = true;
						playAnchor.hide();
						stopAnchor.show();
					}
					else{
						playAnchor.show();
						stopAnchor.hide();
					}
				}	
				
				//Find the first and last thumb
				thumbsList.children("li:first").children("img").addClass("fdGallery_first");
				thumbsList.children("li:last").children("img").addClass("fdGallery_last");
				
				//Hide the image captions
				thumbsList.children("li").each(function(i){
					jQuery(this).height(options.thumbHeight);
					jQuery(this).css({
						height: options.thumbHeight
					});
					jQuery(this).children("span").hide(); 
				});
				
				//Event for previous thumbs list
				thumbNavLeftAnchor.bind("click",previousThumbs);
				
				//Event for next thumbs list
				thumbNavRightAnchor.bind("click",nextThumbs);
				
				//Event for previous image
				previousImageAnchor.bind("click",previousImage);
				prevHoverDiv.bind("click",previousImage);
		
				//Event for next image
				nextImageAnchor.bind("click",nextImage);
				nextHoverDiv.bind("click",nextImage);	
				
				//Enable mouse tracking for the hover
				subDiv.mousemove(function(e){
					var w = subDiv.width();
					var x = e.pageX - subDiv.offset().left;
	      			if(x < w * 0.3){
	      				prevHoverDiv.fadeIn('fast');
	      			}
					else{
						prevHoverDiv.fadeOut('fast');
					}
	      			if(x > w * 0.7){
	      				nextHoverDiv.fadeIn('fast');	
	      			}
					else{
	      				nextHoverDiv.fadeOut('fast');	
	      			}
	   			});
				subDiv.mouseleave(function(){ 
					prevHoverDiv.fadeOut('fast');
					nextHoverDiv.fadeOut('fast'); 
				});
			}

			function imageClick(event, how){
				//Catch when user clicks on an image
				if(how != "auto"){
					if(options.slideEnabled){
						stopAnchor.hide();
						playAnchor.show();
						playing=false;
					}
					mainImg.stop();
					mainImg.dequeue();
					if(options.showCaptions){
						captionDiv.stop();
						captionDiv.dequeue();
					}
				}
				
				//Set the position
				pos = jQuery(this).attr("id").replace("image-","");
				
				//Check if we use user thumbs
				if(options.userThumbs){		
					var imageSource = jQuery(this).attr("ref");
				}
				else{
					var imageSource = this.src;
				}
				var imageLink = jQuery(this).attr("rel");
				var imageCaption = jQuery(this).parent().next("span").html();
				
				//Fade out the old thumb
				images.filter(".fdGallery_selected").fadeTo(250,0.4); 
				images.filter(".fdGallery_selected").removeClass("fdGallery_selected"); 
				
				//Fade in the new thumb
				jQuery(this).fadeTo(250,1);
				jQuery(this).addClass("fdGallery_selected");
				
				//Fade the caption out
				if(options.showCaptions){
					if(options.delayCaption){
						captionDiv.fadeTo(500,0);
					}
					captionDiv.fadeTo(500,0,function(){
						captionDiv.html(imageCaption);
						captionDiv.fadeTo(500,1);
					});
				}
				
				//Show the main image
				mainImg.show();
				
				//Update back image
				backImg.attr("src",mainImg.attr("src"));
				
				var delay = 100;
				if(mainImg.attr('opacity') < 0.8){
					delay = 500;
				}

				//Update main image
				mainImg.fadeTo(delay,0.00,function(){
					mainImg.unbind('load');
					mainImg.bind('load',function(){
						mainImg.fadeTo(800,1,function(){
							//Playing loop
							if(playing){
								jQuery(this).animate({opactiy:1},options.slideSpeed, function(){
									if(playing){
										nextImageAnchor.trigger("click",["auto"]);
									}
								});
							}
							backImg.attr("src",mainImg.attr("src"));
						});
					});
					
					//Set the image source
					mainImg.attr("src",imageSource);
					
					//Set the image link
					mainLink.attr("href",imageLink);
				});
			}
			
			function nextImage(event, how){
				if((parseInt(pos) + 1) % options.thumbs == 0){
					nextThumbs();
				}
				
				if(images.filter(".fdGallery_selected").hasClass("fdGallery_last")){
					stopAnchor.trigger("click");
				}
				else{
					images.filter(".fdGallery_selected").parents('li').next('li').find('img').trigger("click",how);
				}
			}
			
			function previousImage(event, how){
				if(parseInt(pos) % options.thumbs == 0){
					previousThumbs();
				}
				
				if(images.filter(".fdGallery_selected").hasClass("fdGallery_first")){
					stopAnchor.trigger("click");
				}
				else{
					images.filter(".fdGallery_selected").parents('li').prev('li').find('img').trigger("click",how);
				}	
			}
			
			function play(){
				mainDiv.hover(
					function(){
						playDiv.fadeIn(400);
					},
					function(){
						playDiv.fadeOut(400);
					}
				);
				playAnchor.bind("click", function(){
					mainImg.stop();
					mainImg.dequeue();
					if(options.showCaptions){
						captionDiv.stop();
						captionDiv.dequeue();
					}
					playing = true;
					nextImageAnchor.trigger("click",["auto"]);
					jQuery(this).hide();
					stopAnchor.show();
				});
				stopAnchor.bind("click", function(){
					playing = false;
					jQuery(this).hide();
					playAnchor.show();
				});
			}
			
			function updateThumbsNav(){
				var page = Math.ceil(parseInt(pos / options.thumbs));
				
				if(page > 0){
					thumbNavLeftDiv.show();
				}
				else{
					thumbNavLeftDiv.hide();
				}
				
				if(page < parseInt((nbImages - 1)  / options.thumbs)){
					thumbNavRightDiv.show();
				}
				else{
					thumbNavRightDiv.hide();
				}
				
				var thumbsListPadding = (options.width + imageOffsetInner) - (((options.thumbWidth + thumbsOffsetOuter) * options.thumbs));
			
				if(thumbNavLeftDiv.is(':visible')){
					var paddingLeft = (thumbsListPadding - (thumbNavLeftDiv.width() + 3) - (thumbNavRightDiv.width() + 3)) / 2;
				}
				else{
					var paddingLeft = thumbsListPadding / 2;
				}
				
				thumbsContainer.css({
					"padding-left": paddingLeft
				});
 			}
			
			function previousThumbs(){
				var page = parseInt(pos / options.thumbs) - 1;
				if(page * options.thumbs >= 0){
					pos = page * options.thumbs;
					updateThumbsNav();
					thumbsList.animate({left:-(options.thumbWidth + thumbsOffsetOuter) * pos}, "slow");	
				}
			}	
			
			function nextThumbs(){
				var page = parseInt(pos / options.thumbs) + 1;
				if(page * options.thumbs < nbImages){
					pos = page * options.thumbs;
					updateThumbsNav();
					thumbsList.animate({left:-(options.thumbWidth + thumbsOffsetOuter) * pos}, "slow");	
				}
			}
			
			if(options.slideEnabled){
				play();
			}
			activate();
		});
	}
};	
jQuery.fn.FdGallery = jQuery.iFdGallery.build;
