/**
 * Copyright (c) 2011 David Asquiedge (http://book-emoi.com/) - licences (not yet defined)
 * Version: 1.0.0
 *
 * CHEMINEMENT DU PROCESS
 * 1 - fn_adGallery					: retourne toutes les galeries sous forme de tableau
 * 2 - PROTOTYPE_AdGallery 			: définition d'une galerie
 * 3 - PROTOTYPE_AdGallerySlideshow	: définition du slideshow d' une galerie
 * ? - FUNCTIONS					: ( animations / instanciations )
 * 
 * ? - FUNCTION highLightMarque()	: Specificité d HdL - permet de récupérer la class de l'éléments "li" dans "ul.ad-thumb-list" de la galerie et de déclencher une action à partir de chaque changement de vignette
 *
 * Modification de l'affichage de la photo par défaut au chargement de la galerie : ajouter ("#ad-image" + index de l'image)
 * Attribution d'un lien sur l'image dont la valeur peut-être définit par $('img.image0').data('ad-link', 'http://www.hotels-de-luxe.com'); OU par l'attribut "longdesc" de la vignette
 * Attribution d'une description pour l'image dont la valeur peut-être définit par $('img.image0').data('ad-desc', 'description de l'image'); OU par l'attribut "alt" de la vignette
 * Attribution d'un title pour l'image dont la valeur peut-être définit par $('img.image0').data('ad-title', 'titre de l'image'); OU par l'attribut "title" de la vignette
 *
 *
 *
 * gallery based on "http://coffeescripter.com/code/ad-gallery/" (Demo and documentation) - Copyright (c) 2010 Anders Ekdahl (http://coffeescripter.com/) - Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * 
 *
 * chercher "(HDL)" pour trouver les paramètres nécessaires pour les modifications à impacter sur HDL
 * chercher "(???)" pour trouver les commentaires à faire
 */
(function ($) {

	/***fn_adGallery********************************
	 ***										 ***
	 *** INITIALISATION PRINCIPALE DE LA GALERIE ***
	 ***						  		         ***
	 ***********************************************/
	$.fn.adGallery = function (options) {
											var defaults 	= 	{ 	

																	loader_image			: 'modules/galerie/img/loader.gif',								// image afficher lors des chargement d'image ( settings )
																	start_at_index			: 0,															// index de l'image afficher au moment du chargement de la gallerie ( settings )
																	description_wrapper		: false,														// GENERATION HTML DE LA DESCRIPTION ( voir _getDescription()@PROTOTYPE_AdGallery )
																	show_thumb_title		: false,														// Affichage des titles d'image sous les vignettes
																	thumb_opacity			: 0.7,															// opacité des images sans focus ( settings )
																	animate_first_image		: false,														// doit on animer l'image qui s'affiche au chargement de la page ( settings ref : _showWhenLoaded()@PROTOTYPE_AdGallery )
																	animation_speed			: 400,															// rapidité d'execution de l'animation ( settings )
																	width					: false,														// largeur de l'éléments HTML recevant $.fn.adGallery
																	height					: false,														// hauteur de l'éléments HTML recevant $.fn.adGallery
																	display_next_and_prev	: false,														// doit activer les boutons NextAndPrev sur l'image principale ( settings ref : initNextAndPrev()@PROTOTYPE_AdGallery )
																	display_back_and_forward: true,															// doit activer les boutons BackAndForward sur l'image principale ( settings ref : initBackAndForward()@PROTOTYPE_AdGallery )
																	scroll_jump				: 0, // If 0, it jumps the width of the container				// c'est la largeur employée pour faire un saut vers la droite ou la gauche pour avancer dans la navigation des vignettes

																	slideshow				: {																// settings du slideshow ( settings ref : @PROTOTYPE_AdGallerySlideshow )
																									enable			: true,									// Activation du slideshow ( settings ref : initNextAndPrev()@PROTOTYPE_AdGallery )
																									autostart		: true,									// lancement automatique du slideshow ( settings ref : showImage()@PROTOTYPE_AdGallery )
																									stop_on_scroll	: true,									// Arrète le compteur du slideshow au scroll sur les boutons de nav ( settings ref : stop()@PROTOTYPE_AdGallerySlideshow )
																									start_label		: 'Start',								// label du bouton initialisant le compteur ( settings ref : @PROTOTYPE_AdGallerySlideshow )
																									stop_label		: 'Stop',								// label du bouton stopant le compteur ( settings ref : @PROTOTYPE_AdGallerySlideshow )
																									onStart			: false,								// ??? ( settings ref : fireCallback()@PROTOTYPE_AdGallerySlideshow )
																									onStop			: false,								// ??? ( settings ref : fireCallback()@PROTOTYPE_AdGallerySlideshow )
																									countdown_prefix: '(',									// prefix du compteur ( settings ref : _next()@PROTOTYPE_AdGallerySlideshow )
																									countdown_sufix	: ')',									// sufix du compteur ( settings ref : _next()@PROTOTYPE_AdGallerySlideshow )
																									speed			: 5000									// lap de temps entre deux animations ( settings ref : _next()@PROTOTYPE_AdGallerySlideshow )
																							  }, // END slideshow

																	effect					: 'fade', // or 'slide-vert', 'fade', or 'resize', 'none'	// indique le type d'effet a appliquer lors de l'animation
																	enable_keyboard_move	: true,															// autoriser la navigation par clavier
																	cycle					: true,															// autorisé la navigation circulaire

																	callbacks				: {
																									init: false,
																									afterImageVisible: false,
																									beforeImageVisible: false
																							  } // END callbacks

											}; // END VAR defaults
											
											// attribution complète des settings
											var settings = $.extend(false, defaults, options);
											
											// attribution de la valeur slideshow
											if (options && options.slideshow) {
												settings.slideshow = $.extend(false, defaults.slideshow, options.slideshow);
											}; // END IF
											
											// lancement automatique du slideshow
											if (!settings.slideshow.enable) {
												settings.slideshow.autostart = false;
											}; // END IF
											
											// initialisation des galeries
											var galleries 	= [];
											
											// génération de toutes les galeries de la page (instanciation : @PROTOTYPE_AdGallery)
											$(this).each(function() {
												var gallery 				= new AdGallery (this, settings);
												galleries[galleries.length] = gallery;
											}); // END each()@$FN_adGallery()
											
											// Sorry, breaking the jQuery chain because the gallery instances
											// are returned so you can fiddle with them
											return galleries;
											
	}; // END $FN_adGallery()

	/***PROTOTYPE_AdGallery*************************
	 ***										 ***
	 *** INITIALISATION PRINCIPALE DE LA GALERIE ***
	 ***						  		         ***
	 ***********************************************/
	AdGallery.prototype = {
	
		// initialisation des élements
		wrapper				: false,	//	élément HTML définit par "$(wrapper).adGallery()"
		image_wrapper		: false,	//	
		gallery_info		: false,	//	
		nav					: false,	//	
		loader				: false,	//	
		preloads			: false,	//	
		thumbs_wrapper		: false,	//	
		scroll_back			: false,	//	
		scroll_forward		: false,	//	
		next_link			: false,	//	
		prev_link			: false,	//	


		slideshow			: false,	//	
		image_wrapper_width	: 0,		//	
		image_wrapper_height: 0,		//	
		current_index		: 0,		//	
		current_image		: false,	//	
		current_description	: false,	//	
		nav_display_width	: 0,		//	
		settings			: false,	//	
		images				: false,	//	
		in_transition		: false,	//	
		animations			: false,	//	
		
		/*********************************************
		 * fonctions d'initialisation principales	 *
		 *********************************************/
		init : function (wrapper, settings) {
			var context 	= this;
			this.wrapper 	= $(wrapper);
			this.settings	= settings;
			
			this.setupElements();
			this.setupAnimations();
			
			// attribution du width au wrapper
			if (this.settings.width) {
				this.image_wrapper_width = this.settings.width;
				this.image_wrapper.width(this.settings.width);
				this.wrapper.width(this.settings.width);
			} else {
				this.image_wrapper_width = this.image_wrapper.width();
			};
			
			// attribution du height au wrapper
			if (this.settings.height) {
				this.image_wrapper_height = this.settings.height;
				this.image_wrapper.height(this.settings.height);
			} else {
				this.image_wrapper_height = this.image_wrapper.height();
			};
			
			// attribution du height à la nav
			this.nav_display_width = this.nav.width();
			
			// définition de l'index de l'image afficher au démarrage de la galerie 
			this.current_index = 0;
			
			this.current_image 			= false;
			this.current_description 	= false;
			this.in_transition 			= false;
			
			this.findImages(); 																		// Génère les paramètres de chaque image de la barre de navigation ( référence : findImages()@PROTOTYPE_AdGallery)
			
			if (this.settings.display_next_and_prev) {
				this.initNextAndPrev();																// Activation des boutons NextAndPrev sur l'image principale ( settings ref : initNextAndPrev()@PROTOTYPE_AdGallery )
			};
			
			// The slideshow needs a callback to trigger the next image to be shown
			// but we don't want to give it access to the whole gallery instance
			var nextimage_callback = 	function (callback) {
											return context.nextImage(callback);
										};
			
			this.slideshow = new AdGallerySlideshow(nextimage_callback, this.settings.slideshow);	// (instanciation : @PROTOTYPE_AdGallerySlideshow)
			
			this.controls.append(this.slideshow.create());
			
			
			if (this.settings.slideshow.enable) {
				this.slideshow.enable();
			} else {
				this.slideshow.disable();
			}; // END IF
			
			if (this.settings.display_back_and_forward) {
				this.initBackAndForward();
			}; // END IF
			
			if (this.settings.enable_keyboard_move) {
				this.initKeyEvents();
			}; // END IF
			
			
			// attribution de l'index de photo à afficher au chargement de la galerie
			var start_at = parseInt(this.settings.start_at_index, 10);
			if (window.location.hash && window.location.hash.indexOf('#ad-image') === 0) {
				start_at = window.location.hash.replace(/[^0-9]+/g, '');
				if (start_at.length == 0) {
					// Check if it's a number
					start_at = this.settings.start_at_index;
				}
			}; // END IF

			
			this.loading(true);
			
			this.showImage	(
								start_at,
								function() {
									// We don't want to start the slideshow before the image has been
									// displayed
									if (context.settings.slideshow.autostart) {
										context.preloadImage(start_at + 1);
										context.slideshow.start();
									};
								}
							);
			
			this.fireCallback(this.settings.callbacks.init);
		}, // END FUNCTION init()@PROTOTYPE_AdGallery
		
		
		/*********************************************
		 * fonctions d'initialisation complémentaires *
		 *********************************************/
		setupElements: function () {
										this.controls 		= this.wrapper.find('.ad-controls');
										this.gallery_info 	= $('<p class="ad-info"></p>');
										this.controls.append(this.gallery_info);
										this.image_wrapper 	= this.wrapper.find('.ad-image-wrapper');
										this.image_wrapper.empty();
										this.nav = this.wrapper.find('.ad-nav');
										this.thumbs_wrapper = this.nav.find('.ad-thumbs');
										this.preloads 		= $('<div class="ad-preloads"></div>');
										this.loader 		= $('<img class="ad-loader" src="'+ this.settings.loader_image +'" />');
										this.image_wrapper.append(this.loader);
										this.loader.hide();
										$(document.body).append(this.preloads);
									}, // END FUNCTION setupElements()@PROTOTYPE_AdGallery

		setupAnimations: function () {
			this.animations = 	{
									'slide-vert': VerticalSlideAnimation,
									'slide-hori': HorizontalSlideAnimation,
									'resize': ResizeAnimation,
									'fade': FadeAnimation,
									'none': NoneAnimation
								};
		}, // END FUNCTION setupAnimations()@PROTOTYPE_AdGallery
		

		loading: function (bool) {
			if (bool) {
				this.loader.show();
			} else {
				this.loader.hide();
			};
		}, // END FUNCTION loading()@PROTOTYPE_AdGallery
		
		addAnimation: function (name, fn) {
			if ($.isFunction(fn)) {
				this.animations[name] = fn;
			};
		}, // END FUNCTION addAnimation()@PROTOTYPE_AdGallery
		
		/******************************************************
		 ***						  						***
		 *** RECUPERER LES INFORMATIONS NECESSAIRES 		***
		 *** AU FONCTIONNEMENT DU CARROUSEL			 		***
		 *** EN LISTANT LES IMAGES SE TROUVANTS DANS LA NAV	***
		 *** ET ATTRIBUTION DE LA LARGEUR A LA NAV			***
		 ***						  						***
		 ******************************************************/
		findImages: function () {
		
			var context 			= this;																			// context = la gallerie concernée

			this.images 			= [];																			// tableau destiné à stocker les informations concernant les images présentes dans la nav

			var thumb_wrapper_width = 0;																			// Initialisation de la largeur de la nav

			var thumbs_loaded 		= 0;																			// Initialisation du nombre d'images loadées

			var thumbs 				= this.thumbs_wrapper.find('a');												// Identification des vignettes par leur lien 

			var thumb_count 		= thumbs.length;																// Attribution du nombre total de vignettes
			
			if (this.settings.thumb_opacity < 1) {
				thumbs.find('img').css('opacity', this.settings.thumb_opacity);										// Attribution de l'opacité souhaitée à chaque vignette
			};
			
			
			thumbs.each( function(i) {
			
				var link 		= $(this);																			// pour ce lien
				
				if (link.attr('title').length > 0) {															// on récupère la src de l'image ou le lien à suivre
					var image_src 	= link.attr('title');
				} else {
					var image_src 	= link.attr('href');
				}
				var thumb 		= link.find('img');																	// on récupère la vignette
				
				// Si la première vignette n'a pas été chargée 
				if (!context.isImageLoaded(thumb[0])) {
					thumb.load(	function() {
						thumb_wrapper_width += this.parentNode.parentNode.offsetWidth;
						thumbs_loaded++;
					});
				// si l'image a été chargée
				} else {
					thumb_wrapper_width += thumb[0].parentNode.parentNode.offsetWidth;
					thumbs_loaded++;
				};
				
				link.addClass('ad-thumb'+ i);
				
				// CLICK : on montre le contenu dans le wrapper et l'on arrête le slide show si la vignette ne contient pas de title
				if (link.attr('title').length == 0) {
					link.click(	function() {
						context.showImage(i);
						/* (HDL) prévoir de faire redémarrer le slideshow après un certain temps */
						context.slideshow.stop();
						return false;
					/* (HDL) HOVER DESACTIVE */
					// ROLL OVER : opacity de la vignette à 1 et preload de l'image concernée ET ROLL OUT : opacity à la normal
					// }).hover(
						// function () {
							// if (!$(this).is('.ad-active') && context.settings.thumb_opacity < 1) {
								// $(this).find('img').fadeTo(300, 1);
							// };
							// context.preloadImage(i);
						// },
						// function() {
							// if(!$(this).is('.ad-active') && context.settings.thumb_opacity < 1) {
								// $(this).find('img').fadeTo(300, context.settings.thumb_opacity);
							// };
						// }
					// );
					});
				}
				
				/**********************
				 * DEFINITION UN LIEN *
				 **********************/
				var link = false;
				if (thumb.data('ad-link')) {
					link = thumb.data('ad-link');
				} else if (thumb.attr('longdesc') && thumb.attr('longdesc').length) {
					link = thumb.attr('longdesc');
				};
								
				/******************************
				 * DEFINITION UNE DESCRIPTION *
				 ******************************/
				var desc = false;
				if(thumb.data('ad-desc')) {
					desc = thumb.data('ad-desc');
				} else if (thumb.attr('alt') && thumb.attr('alt').length) {
					desc = thumb.attr('alt');
				};
				
				/***********************
				 * DEFINITION UN TITRE *
				 ***********************/
				var title = false;
				if (thumb.data('ad-title')) {
					title = thumb.data('ad-title');
				} else if (thumb.attr('title') && thumb.attr('title').length) {
					title = thumb.attr('title');
				};
				
				/**ATTRIBUTION DES VARIABLES**************************************************************
				 *																						 *
				 * (HDL) 																		 		 *
				 * DEFINITION DES VARIABLES DE LA VIGNETTE ET DE SON IMAGE 					 			 *
				 * OU CODE HTML AUQUELLE ELLE SE RAPPORTE												 *
				 *																						 *
				 *****************************************************************************************/
				context.images[i] = 	{ 
											thumb		: thumb.attr('src'), 
											image		: image_src, 
											error		: false,
											preloaded	: false, 
											desc		: desc, 
											title		: title, 
											size		: false,
											link		: link
										};
			}); // END thumbs.each() in findImages()@PROTOTYPE_AdGallery
			
			
			// Attribuer la largeur à la liste après que les vignettes aient été toutes loadées
			var inter = setInterval ( function() {
										if (thumb_count == thumbs_loaded) {
										
											thumb_wrapper_width -= 50;
											var list 			 = context.nav.find('.ad-thumb-list');
											list.css('width', thumb_wrapper_width +'px');
											
											var i 			= 1;
											var last_height = list.height();
											
											while(i < 201) {
												list.css('width', (thumb_wrapper_width + i) +'px');
												if(last_height != list.height()) {
													break;
												}
												last_height = list.height();
												i++;
											}
											clearInterval(inter);
										};
									}, 100);
		}, // END FUNCTION findImages()@PROTOTYPE_AdGallery

		/******************************************************
		 ***						  						***
		 *** ATTRIBUTON D'EVENEMENTS AUX TOUCHES CLAVIER	***
		 ***						  						***
		 ******************************************************/
		initKeyEvents: function () {
			var context = this;
			$(document).keydown( function(e) {
				if (e.keyCode == 39) {
					// right arrow
					context.nextImage();
					context.slideshow.stop();
				} else if (e.keyCode == 37) {
					// left arrow
					context.prevImage();
					context.slideshow.stop();
				};
			});
		}, // END FUNCTION initKeyEvents()@PROTOTYPE_AdGallery

		
		/***initNextAndPrev()@PROTOTYPE_AdGallery**************
		 ***						  						***
		 *** INITIALISATION DU CODE HTML ET DES EVENEMENT	***
		 *** SUR LES BOUTONS COUVRANT LE CONTENU			***
		 ***						  						***
		 ******************************************************/
		initNextAndPrev: function() {
			this.next_link 	= $('<div class="ad-next"><div class="ad-next-image"></div></div>');
			this.prev_link 	= $('<div class="ad-prev"><div class="ad-prev-image"></div></div>');
			this.image_wrapper.append(this.next_link);
			this.image_wrapper.append(this.prev_link);
			var context 	= this;
			
			/* js d'origine
			this.prev_link.add(this.next_link).mouseover( function(e) {
				// IE 6 hides the wrapper div, so we have to set it's width
				$(this).css('height', context.image_wrapper_height);
				$(this).find('div').show();
			}).mouseout( function(e) {
				$(this).find('div').hide();
			}).click( function() {
				if($(this).is('.ad-next')) {
					context.nextImage();
					context.slideshow.stop();
				} else {
					context.prevImage();
					context.slideshow.stop();
				};
			}).find('div').css('opacity', 0.7);
			*/
			/* hdl nouveau code js */
			this.prev_link.add(this.next_link).click( function() {
				if($(this).is('.ad-next')) {
					context.nextImage();
					context.slideshow.stop();
				} else {
					context.prevImage();
					context.slideshow.stop();
				};
			}).find('div').css('opacity', 0.7).show();
		}, // END FUNCTION initNextAndPrev()@PROTOTYPE_AdGallery

		
		/***initBackAndForward()@PROTOTYPE_AdGallery*************
		 ***						  						***
		 *** INITIALISATION DU CODE HTML ET DES EVENEMENT	***
		 *** SUR LES BOUTONS DE NAV							***
		 ***						  						***
		 ******************************************************/
		initBackAndForward: function() {
			var context 				= this;
			this.scroll_forward 		= $('<div class="ad-forward"></div>');
			this.scroll_back 			= $('<div class="ad-back"></div>');
			this.nav.append(this.scroll_forward);
			this.nav.prepend(this.scroll_back);
			var has_scrolled 			= 0;
			var thumbs_scroll_interval 	= false;
			
			$(this.scroll_back).add(this.scroll_forward).click( function() {
				// We don't want to jump the whole width, since an image
				// might be cut at the edge
				var width = context.nav_display_width - 50;

				if (context.settings.scroll_jump > 0) {
					var width = context.settings.scroll_jump;
				};
				
				if ($(this).is('.ad-forward')) {
					var left = context.thumbs_wrapper.scrollLeft() + width;
				} else {
					var left = context.thumbs_wrapper.scrollLeft() - width;
				};
				
				if (context.settings.slideshow.stop_on_scroll) {
					context.slideshow.stop();
				};
				
				context.thumbs_wrapper.animate({scrollLeft: left +'px'});
				return false;
			}
			/* js d'origine
			).css('opacity', 0.6).hover( 
				function() {
					var direction = 'left';
					if ($(this).is('.ad-forward')) {
						direction = 'right';
					};
					thumbs_scroll_interval = setInterval( function() {
						has_scrolled++;
						// Don't want to stop the slideshow just because we scrolled a pixel or two
						if (has_scrolled > 30 && context.settings.slideshow.stop_on_scroll) {
							context.slideshow.stop();
						};
						var left = context.thumbs_wrapper.scrollLeft() + 1;
						if (direction == 'left') {
							left = context.thumbs_wrapper.scrollLeft() - 1;
						};
						context.thumbs_wrapper.scrollLeft(left);
					}, 10);
					$(this).css('opacity', 1);
				},
				function() {
					has_scrolled = 0;
					clearInterval(thumbs_scroll_interval);
					$(this).css('opacity', 0.6);
				}
			);
			*/
			/* hdl nouveau js */
			).css('opacity', 1);
		}, // END FUNCTION initBackAndForward()@PROTOTYPE_AdGallery


		/******************************************************
		 ***						  						***
		 *** ????????????????????????????????????????????	***
		 ***						  						***
		 ******************************************************/
		_afterShow: function() {
			this.gallery_info.html((this.current_index + 1) +' / '+ this.images.length);
			if (!this.settings.cycle) {
				// Needed for IE
				this.prev_link.show().css('height', this.image_wrapper_height);
				this.next_link.show().css('height', this.image_wrapper_height);
				if (this.current_index == (this.images.length - 1)) {
					this.next_link.hide();
				};
				if (this.current_index == 0) {
					this.prev_link.hide();
				};
			};
			this.fireCallback(this.settings.callbacks.afterImageVisible);
		}, // END FUNCTION _afterShow()@PROTOTYPE_AdGallery


		/**
		 * Checks if the image is small enough to fit inside the container
		 * If it's not, shrink it proportionally
		 */
		_getContainedImageSize: function(image_width, image_height) {
			if (image_height > this.image_wrapper_height) {
				var ratio 		= image_width / image_height;
				image_height 	= this.image_wrapper_height;
				image_width 	= this.image_wrapper_height * ratio;
			};
			if(image_width > this.image_wrapper_width) {
				var ratio 		= image_height / image_width;
				image_width 	= this.image_wrapper_width;
				image_height 	= this.image_wrapper_width * ratio;
			};
			return 	{
						width	: image_width, 
						height	: image_height
					};
		}, // END FUNCTION _getContainedImageSize()@PROTOTYPE_AdGallery


		/**
		 * If the image dimensions are smaller than the wrapper, we position
		 * it in the middle anyway
		 */
		_centerImage: function (img_container, image_width, image_height) {
			img_container.css('top', '0px');
			if (image_height < this.image_wrapper_height) {
				var dif = this.image_wrapper_height - image_height;
				img_container.css('top', (dif / 2) +'px');
			};
			img_container.css('left', '0px');
			if (image_width < this.image_wrapper_width) {
				var dif = this.image_wrapper_width - image_width;
				img_container.css('left', (dif / 2) +'px');
			};
		}, // END FUNCTION _centerImage()@PROTOTYPE_AdGallery


		/***_getDescription()@PROTOTYPE_AdGallery**********************
		 ***						  								***
		 *** GENERATION HTML DE LA BALISE P.ad-image-description	***
		 *** CONTENANT LE TITLE + DESC DE L IMAGE					***
		 ***						  								***
		 **************************************************************/
		_getDescription: function (image) {
			var desc = false;
			if (image.desc.length || image.title.length) {
				var title = '';
				if (image.title.length && image.title != 'no-title') {
					title = '<strong class="ad-description-title">'+ image.title +'</strong>';
				};
				var desc = '';
				if (image.desc.length && image.title != 'no-title') {
					desc = '<span>'+ image.desc +'</span>';
				};
				if ( image.title == 'no-title') {
					desc = $(image.desc);
				} else {
					desc = $('<p class="ad-image-description">'+ title + desc +'</p>');
				}
			};
			return desc;
		}, // END FUNCTION _getDescription()@PROTOTYPE_AdGallery


		/**
		 * @param function callback Gets fired when the image has loaded, is displaying
		 *                          and it's animation has finished
		 */
		/* (HDL) transformer la fonction pour permettre l'affichage d'un code HTML plutot qu'une img uniquement*/
		showImage: function (index, callback) {
			if (this.images[index] && !this.in_transition) {
				var context 		= this;
				var image 			= this.images[index];
				this.in_transition 	= true;
				if (!image.preloaded) {
					this.loading(true);
					this.preloadImage(index, function() {
						context.loading(false);
						context._showWhenLoaded(index, callback);
					});
				} else {
					this._showWhenLoaded(index, callback);
				};
			};
		}, // END FUNCTION showImage()@PROTOTYPE_AdGallery


		/***_showWhenLoaded()@PROTOTYPE_AdGallery**********************************************
		 **************************************************************************************
		 *** @param function callback Gets fired when the image has loaded, is displaying	***
		 ***                          and it's animation has finished						***
		 *** 																				***
		 ***  _showWhenLoaded: function(index, callback) { ... }							***
		 *** 																				***
		 *** 	index    => index de l'image  												***
		 ***	callback => function () {													***
		 ***					if (context.settings.slideshow.autostart) {					***
		 ***						context.preloadImage(start_at + 1);						***
		 ***						context.slideshow.start();								***
		 ***					}															***
		 ***				}																***
		 **************************************************************************************	
		 **************************************************************************************/
		_showWhenLoaded: function (index, callback) {
			/* identification du contenu visé par son index */
			if (this.images[index]) {
					var context 	= this;
					var image 		= this.images[index];
				// alert(dump(image));
				/* création du conteneur de contenu */
				var img_container 	= $(document.createElement('div')).addClass('ad-image');
				
				/* (HDL) création du conteneur à afficher */
				// if(1) {
				  // /* IMAGE */
				  var img = $(new Image()).attr('src', image.image);
				// } else {
				  // /* HTML */
				  // var html = $(new Image()).attr('src', image.image);
				// }
				
				// génération de l'anchor de la vignette
				if(image.link) {
				  var link = $('<a href="'+ image.link +'" target="_self"></a>');
				  link.append(img);
				  img_container.append(link);
				/* (HDL) */
				// } else if (0) {
				  // img_container.append(html);
				} else {
				  img_container.append(img);
				}
				
				this.image_wrapper.prepend(img_container);
				
				/* SIZE */
				var size = this._getContainedImageSize(image.size.width, image.size.height);
				img.attr('width', size.width);
				img.attr('height', size.height);
				img_container.css( {
										width	: size.width  +'px', 
										height	: size.height +'px'
									});
				this._centerImage(img_container, size.width, size.height);
				
				/* GENERATION HTML DE LA DESCRIPTION ( voir _getDescription()@PROTOTYPE_AdGallery ) */
				var desc = this._getDescription(image, img_container);

				if (desc) {
					if (!this.settings.description_wrapper) {
						img_container.append(desc);
						var width = size.width - parseInt(desc.css('padding-left'), 10) - parseInt(desc.css('padding-right'), 10);
						desc.css('width', width +'px');
					} else {
						this.settings.description_wrapper.append(desc);
					}
				};
				
				/* HIGHLIGHTTHUMB */
				this.highLightThumb(this.nav.find('.ad-thumb'+ index));
				
				/* HIGHLIGHTMARQUE */
				type = this.nav.find('.ad-thumb'+ index).parent().attr('class');
				if ( type.length > 0 ) {
					this.highLightMarque(type);
				}
				
				/* SHOWTHUMBTITLE */
				if (this.settings.show_thumb_title) {
					this.showThumbTitle(this.nav.find('.ad-thumb'+ index));
				}
				
				/* DIRECTION */
				var direction = 'right';
				if (this.current_index < index) {
					direction = 'left';
				};
				
				this.fireCallback(this.settings.callbacks.beforeImageVisible);
				
				// si il y a une nouvelle image à afficher ou si il faut animer la première image
				if (this.current_image || this.settings.animate_first_image) {
					var animation_speed = this.settings.animation_speed;
					var easing 			= 'swing';
					var animation 		= this.animations[this.settings.effect].call(this, img_container, direction, desc);
					
					// default animation.speed
					if (typeof animation.speed != 'undefined') {
						animation_speed = animation.speed;
					};
					
					// default animation.easing
					if (typeof animation.easing != 'undefined') {
						easing = animation.easing;
					};
					
					// definit l'animation de disparition de l'image en cours
					if (this.current_image) {
						var old_image = this.current_image;
						var old_description = this.current_description;
						
						old_image.animate(
							animation.old_image, 
							animation_speed, 
							easing,
							function() {
								old_image.remove();
								if (old_description) {
									old_description.remove();
								}
							}
						);
					};
					
					// definit l'animation de la nouvelle image
					img_container.animate(
						animation.new_image, 
						animation_speed, 
						easing,
						function() {
							context.current_index = index;
							context.current_image = img_container;
							context.current_description = desc;
							context.in_transition = false;
							context._afterShow();
							context.fireCallback(callback);
						}
					);
				
				// Si l'image n'a pas changée (rechargement page)
				} else {
					this.current_index 			= index;
					this.current_image 			= img_container;
					context.current_description = desc;
					this.in_transition 			= false;
					
					context._afterShow();
					
					this.fireCallback(callback);
				};
			};
		}, // END FUNCTION _showWhenLoaded()@PROTOTYPE_AdGallery
		
		
		// défini la prochaine image à 
		// 0 		: si on est à la fin de la liste 
		// +1 		: s'il en reste
		// false 	: si le carrousel cyclique n'est pas autorisé
		nextIndex: function() {
			if (this.current_index == (this.images.length - 1)) {
				if(!this.settings.cycle) {
					return false;
				};
				var next = 0;
			} else {
				var next = this.current_index + 1;
			};
			return next;
		}, // END FUNCTION nextIndex()@PROTOTYPE_AdGallery
		
		
		// affichage de la prochaine image conditionnel
		// renvoi false si l'on est en fin de'un carrousel non cyclique
		// montre la prochaine image et preload la suivante
		nextImage: function (callback) {
			var next = this.nextIndex();
			if	(next === false) {
				return false;
			}
			this.preloadImage(next + 1);
			this.showImage(next, callback);
			return true;
		}, // END FUNCTION nextImage()@PROTOTYPE_AdGallery
		
		
		prevIndex: function() {
		  if(this.current_index == 0) {
			if(!this.settings.cycle) {
			  return false;
			};
			var prev = this.images.length - 1;
		  } else {
			var prev = this.current_index - 1;
		  };
		  return prev;
		}, // END FUNCTION prevIndex()@PROTOTYPE_AdGallery
		prevImage: function(callback) {
		  var prev = this.prevIndex();
		  if(prev === false) return false;
		  this.preloadImage(prev - 1);
		  this.showImage(prev, callback);
		  return true;
		}, // END FUNCTION prevImage()@PROTOTYPE_AdGallery
		preloadAll: function() {
		  var context = this;
		  var i = 0;
		  function preloadNext() {
			if(i < context.images.length) {
			  i++;
			  context.preloadImage(i, preloadNext);
			};
		  };
		  context.preloadImage(i, preloadNext);
		}, // END FUNCTION preloadAll()@PROTOTYPE_AdGallery
		
		
		preloadImage: function (index, callback) {
			if (this.images[index]) {
				var image = this.images[index];
				if (!this.images[index].preloaded) {
					var img = $(new Image());
					img.attr('src', image.image);
					if(!this.isImageLoaded(img[0])) {
						this.preloads.append(img);
						var context = this;
						img.load( function() {
							image.preloaded = true;
							image.size = 	{ 
												width	: this.width, 
												height	: this.height };
							context.fireCallback(callback);
						}).error( function() {
								image.error 	= true;
								image.preloaded = false;
								image.size 		= false;
						});
					} else {
						image.preloaded = true;
						image.size = 	{ 
											width	: img[0].width, 
											height	: img[0].height 
										};
						this.fireCallback(callback);
					};
				} else {
					this.fireCallback(callback);
				};
			};
		}, // END FUNCTION preloadImage@PROTOTYPE_AdGallery

		
		// vérification du chargement de la vignette de nav
		// retourne true si l'image existe déjà
		// retourne faux si (???)
		isImageLoaded: function	(img) {
			if(typeof (img.complete) != 'undefined' && !img.complete) {
				return false;
			};
			
			if(typeof (img.naturalWidth) != 'undefined' && img.naturalWidth == 0) {
				return false;
			};
			return true;
		},

		
		highLightThumb: function (thumb) {
			this.thumbs_wrapper.find('.ad-active').removeClass('ad-active');
			thumb.addClass('ad-active');

			if (this.settings.thumb_opacity < 1) {
				this.thumbs_wrapper.find('a:not(.ad-active) img').fadeTo(300, this.settings.thumb_opacity);
				thumb.find('img').fadeTo(300, 1);
			};
			var left = thumb[0].parentNode.offsetLeft;
			left -= (this.nav_display_width / 2) - (thumb[0].offsetWidth / 2);
			this.thumbs_wrapper.animate({scrollLeft: left +'px'});
		},
		
		highLightMarque: function (type) {
			if ( typeof(marque) == 'undefined' ) {
				marque = 'chaine';
				jQuery('.marques').css('opacity',this.settings.thumb_opacity);
				jQuery('.marques.'+marque).css('opacity','1');
			}
			if ( marque != type ) {
				jQuery('.marques.'+marque).css('opacity',this.settings.thumb_opacity);
				jQuery('.marques.'+type).css('opacity','1');
				marque = type;
			}
		},
		
		showThumbTitle: function (thumb) {
			this.nav.find('span').remove();
			thumb.append('<span style="display:block; width:100%; " ><img style="margin:0 auto;" src="modules/galerie/img/indicateArticle.png" height="12" width="12" /></span>');
			this.nav.append('<span>' + thumb.find('img').attr('title') + '</span>');
		},
		
		fireCallback: function (fn) {
			if($.isFunction(fn)) {
				fn.call(this);
			};
		}
	}; // PROTOTYPE AdGallery

	/***PROTOTYPE_AdGallerySlideshow********************
	 ***											 ***
	 *** INITIALISATION COMPLEMENTAIRE DE LA GALERIE ***
	 ***						  		    	     ***
	 ***************************************************/
	AdGallerySlideshow.prototype = {
		
		start_link			: false,
		stop_link			: false,
		countdown			: false,
		controls			: false,

		settings			: false,
		nextimage_callback	: false,
		enabled				: false,
		running				: false,
		countdown_interval	: false,
		
		init: function (nextimage_callback, settings) {
			var context 			= this;
			this.nextimage_callback = nextimage_callback;
			this.settings 			= settings;
		}, // END FUNCTION init()@PROTOTYPE_AdGallerySlideshow
		
		create: function () {
			this.start_link = $('<span class="ad-slideshow-start">'+ this.settings.start_label +'</span>');
			this.stop_link 	= $('<span class="ad-slideshow-stop">'+ this.settings.stop_label +'</span>');
			this.countdown 	= $('<span class="ad-slideshow-countdown"></span>');
			this.controls 	= $('<div class="ad-slideshow-controls"></div>');
			this.controls.append(this.start_link).append(this.stop_link).append(this.countdown);
			this.countdown.hide();

			var context = this;
			
			this.start_link.click( function() {
				context.start();
			});
			this.stop_link.click( function() {
				context.stop();
			});
			
			$(document).keydown( function(e) {
				if(e.keyCode == 83) {
					// 's'
					if(context.running) {
						context.stop();
					} else {
						context.start();
					};
				};
			});
			
			return this.controls;
		}, // END FUNCTION create()
		
		disable: function () {
			this.enabled = false;
			this.stop();
			this.controls.hide();
		}, // END FUNCTION disable()
		enable: function () {
			this.enabled = true;
			this.controls.show();
		}, // END FUNCTION enable()
		toggle: function () {
			if (this.enabled) {
				this.disable();
			} else {
				this.enable();
			};
		}, // END FUNCTION toggle()
		
		start: function	() {
			if(this.running || !this.enabled) {
				return false;
			} // END IF
			var context  = this;
			this.running = true;
			this.controls.addClass('ad-slideshow-running');
			this._next();
			this.fireCallback(this.settings.onStart);
			return true;
		}, // END FUNCTION start() 
		stop: function () {
			if(!this.running) {
				return false;
			} // END IF
			this.running = false;
			this.countdown.hide();
			this.controls.removeClass('ad-slideshow-running');
			clearInterval(this.countdown_interval);
			this.fireCallback(this.settings.onStop);
			return true;
		}, // END FUNCTION stop() 
		
		_next: function() {
			var context = this;
			var pre 	= this.settings.countdown_prefix;
			var su 		= this.settings.countdown_sufix;
			
			clearInterval(context.countdown_interval);
			
			this.countdown.show().html(pre + (this.settings.speed / 1000) + su);
			
			var slide_timer = 0;
			
			this.countdown_interval = 	setInterval( function() {
			
											slide_timer += 1000;
											
											if (slide_timer >= context.settings.speed) {			
												var whenNextIsShown = 	function() {
																			// A check so the user hasn't stoped the slideshow during the
																			// animation
																			if (context.running) {
																				context._next();
																			}; // END IF
																		
																			slide_timer = 0;
																			
																		};
												
												if (!context.nextimage_callback(whenNextIsShown)) {
													context.stop();
												};
												
												slide_timer = 0;
											}; // END IF
											
											var sec = parseInt(context.countdown.text().replace(/[^0-9]/g, ''), 10);
											sec--;
											
											if (sec > 0) {
												context.countdown.html(pre + sec + su);
											};
										}, 1000);

		}, // END FUNCTION _next()@PROTOTYPE_AdGallerySlideshow
		
		fireCallback: function(fn) {
			if ($.isFunction(fn)) {
				fn.call(this);
			}; // END FUNCTION fireCallback()@PROTOTYPE_AdGallerySlideshow
			
		} // END FUNCTION fireCallback()
		
	}; // PROTOTYPE AdGallerySlideshow
	
	/***FUNCTIONS**********************************************
	 ***												    ***
	 *** DEFINITION DES FUNCTIONS COMPLEMENTAIRES		    ***
	 ***						  		         			***
	 **********************************************************/
	/*****************************
     * fonctions d'animations    *
	 *****************************/
	function VerticalSlideAnimation (img_container, direction, desc) {
		var current_top = parseInt(img_container.css('top'), 10);
		if (direction == 'left') {
			var old_image_top = '-'+ this.image_wrapper_height +'px';
			img_container.css('top', this.image_wrapper_height +'px');
		} else {
			var old_image_top = this.image_wrapper_height +'px';
			img_container.css('top', '-'+ this.image_wrapper_height +'px');
		};
		if(desc) {
			desc.css('bottom', '-'+ desc[0].offsetHeight +'px');
			desc.animate({bottom: 0}, this.settings.animation_speed * 2);
		};
		if(this.current_description) {
			this.current_description.animate({bottom: '-'+ this.current_description[0].offsetHeight +'px'}, this.settings.animation_speed * 2);
		};
		return {old_image: {top: old_image_top},
            new_image: {top: current_top}};
	}; // END FUNCTION VerticalSlideAnimation()

	function HorizontalSlideAnimation(img_container, direction, desc) {
		var current_left = parseInt(img_container.css('left'), 10);
		if (direction == 'left') {
			var old_image_left = '-'+ this.image_wrapper_width +'px';
			img_container.css('left',this.image_wrapper_width +'px');
		} else {
			var old_image_left = this.image_wrapper_width +'px';
			img_container.css('left','-'+ this.image_wrapper_width +'px');
		};
		if (desc) {
			desc.css('bottom', '-'+ desc[0].offsetHeight +'px');
			desc.animate({bottom: 0}, this.settings.animation_speed * 2);
		};
    
		if (this.current_description) {
			this.current_description.animate({bottom: '-'+ this.current_description[0].offsetHeight +'px'}, this.settings.animation_speed * 2);
		};
    
		return {old_image: {left: old_image_left},
            new_image: {left: current_left}};
	}; // END FUNCTION HorizontalSlideAnimation()

	function ResizeAnimation(img_container, direction, desc) {
		var image_width = img_container.width();
		var image_height = img_container.height();
		var current_left = parseInt(img_container.css('left'), 10);
		var current_top = parseInt(img_container.css('top'), 10);
		img_container.css({width: 0, height: 0, top: this.image_wrapper_height / 2, left: this.image_wrapper_width / 2});
		return {old_image: {width: 0,
							height: 0,
							top: this.image_wrapper_height / 2,
							left: this.image_wrapper_width / 2},
				new_image: {width: image_width,
							height: image_height,
							top: current_top,
							left: current_left}};
	}; // END FUNCTION ResizeAnimation()

	function FadeAnimation(img_container, direction, desc) {
		img_container.css('opacity', 0);
		return {old_image: {opacity: 0},
				new_image: {opacity: 1}};
	}; // END FUNCTION FadeAnimation()

  // Sort of a hack, will clean this up... eventually
	function NoneAnimation(img_container, direction, desc) {
		img_container.css('opacity', 0);
		return {old_image: {opacity: 0},
				new_image: {opacity: 1},
				speed: 0};
	}; // END FUNCTION NoneAnimation()

	
	/*****************************
     * fonctions d'instanciation *
	 *****************************/
	// initialisation de la galerie
	function AdGallery(wrapper, settings) {
		this.init(wrapper, settings);
	}; // END FUNCTION AdGallery()

	// initialisation du slideshow de la galerie
	function AdGallerySlideshow(nextimage_callback, settings) {
		this.init(nextimage_callback, settings);
	}; // END FUNCTION AdGallerySlideshow()


})(jQuery);
