/**
 * Zoom Images
 * @version 1.1.2
 * @system2s
 * @author deuxsucres
 *
 * Permet l'affichage zoomé d'une image depuis une série de vignettes.
 * Recherche dans la page toutes les zones d'affichage de vignettes (classe zoomimages).
 * Lors d'un clique sur l'une de ces vignettes, affiche une lightBox contenant l'image en taille max.
 * Un clique sur l'image dans la lightbox permet de fermer la lightbox.
 *
 * CHANGELOG
 *  - v 1.1.2 - Ajout d'une sécurité empêchant le traitement multiple d'une même zone.
 *  - v 1.1.1 - Correction d'un bug : suppression de l'attribut src de la balise image du MinViewer qui forçait un chargement inutile de la page d'accueil du site.
 *  - v 1.1   - Redimensionnement automatique de l'image si sa taille est supérieure à la taille du client.
 *            - Redimensionnement automatique de la lightbox sur redimensionnement du client.
 *            - Correction du problème de centrage.
 *  - v 1     - Première version.
 *
 * INFOS
 * Composant développé pour System2s
 *
 * REQUIS
 *  - JQuery 1.3.2
 *
 * COMPATIBILITÉ
 *  - Firefox 3
 *  - Opera 10
 *  - Safari 3
 *  - Chrome 1
 *  - IE 7
 *
 * NOTES
 *  - Ne prend pas encore en compte le vrai nom de l'image à zoomer. Se contente de renommer l'image vignette '*-min.*' en '*-max.jpg'.
 *  - Il y a trop de couplage entre les CSS de la lightbox et le code Javascript.
 *
 * BUGS
 *  - Les erreurs de chargement, si une image n'existe pas, ne sont pas gérées.
 */

/**
 * Composant d'affichage de l'image zoomé.
 */
var ImagesZoomBox = function() {

	/**
	 * (Objet jQuery) Masque global.
	 */
	this._mask = $('<div id="mask"></div>') ;

	/**
	 * (Objet jQuery) Conteneur
	 */
	this._box = $('<div id="imgViewer" style="z-index:1000"><div class="corner tl"></div> <div class="corner tr"></div> <div class="corner bl"></div><div class="corner br"></div><div class="button close"></div><div class="button previous"></div><div class="button next"></div><img alt="" /><h3></h3></div>') ;

	/**
	 * (Objet jQuery) Balise img conteneur de l'image.
	 */
	this._image ;

	/**
	 * (Objet jQuery) Balise img loader de l'image.
	 */
	this._imageLoader = $('<img />') ;

	/**
	 * (Objet jQuery) Balise h3 conteneur du titre.
	 */
	this._title ;

	/**
	 * (Objet jQuery) Bouton de fermeture.
	 */
	this._btClose ;

	/**
	 * (Objet jQuery) Bouton précédent.
	 */
	this._btPrevious ;

	/**
	 * (Objet jQuery) Bouton suivant.
	 */
	this._btNext ;

	/**
	 * (Array) Liste des images à afficher.
	 */
	this._images ;

	/**
	 * (uint) Image actuellement affichée. Correspond à l'index de l'image dans le tableau this._images
	 */
	this._current = 0 ;

	/**
	 * (boolean) Indique qu'une image est actuellement affichée.
	 */
	this._showing = false ;

	/**
	 * Constructeur.
	 */

	//Paramètrage du masque
	this._mask.css({
		top: "0",
		left: "0",
		position: "absolute",
		opacity: 0.2
	}) ;

	//Paramètrage du conteneur.
	this._box.hide() ;
	this._box.css({
		position: "fixed"
	}) ;

	//Récupération du conteneur image
	this._image = $('img', this._box) ;

	//Récupération du loader image
	this._imageLoader ;

	//Récupération du conteneur titre
	this._title = $('h3', this._box) ;

	//Récupération du bouton de fermeture
	this._btClose = $('.button.close', this._box) ;

	//Récupération du bouton précédent
	this._btPrevious  = $('.button.previous', this._box) ;

	//Récupération du bouton suivant
	this._btNext = $('.button.next', this._box) ;

	this._btClose.bind("click", this, function(event) { event.data._hide() } ) ;
	this._image.bind("click", this, function(event) { event.data._hide() } ) ;
	this._imageLoader.bind("load", this, function(event) { event.data._imgLoadHandler() } ) ;
	this._btPrevious.bind("click", this, function(event) { event.data._previous(event) } ) ;
	this._btNext.bind("click", this, function(event) { event.data._next(event) } ) ;
	$(window).bind("resize", this, function(event) { event.data._resize(event) } ) ;

	//Ajoute le masque et le conteneur à la page
	$('body').append(this._mask) ;
	$('body').append(this._box) ;
} ;

	//Méthodes publiques

    /**
     * Déclenché lorsque la fenêtre se redimensionne
     */
	ImagesZoomBox.prototype._resize = function(event) {
		//Si aucune image n'est affichée, ne tient pas compte de l'event.
		if(!this._showing) {
			return ;
		}

		//Force un redimensionnement du masque pour éviter les problèmes de scrollbar
		this._mask.css({
			width: $(window).width() + "px",
			height: $(window).height() + "px"
		}) ;

		//Réaffiche l'image en cours.
		this._show(this._current) ;
	} ;

	/**
	 * Affiche la lightbox et affiche l'image estraite du tableau images à l'index current.
	 * Si le tableau images est vide, rien ne se passe.
	 * Si current n'est pas défini, sa valeur est fixée à 0.
	 * @param	images	(Array)	Tableau peuplé d'objets définissant l(es) image(s) à afficher. Ces objets doivent avoir 2 propriétés : source et title.
	 * @param current	(uint)	Id de l'objet dans le tableau à afficher.
	 */
	ImagesZoomBox.prototype.show = function(images, current) {

		//Aucune image à afficher, annule.
		if(images.length == 0) {
			return ;
		}

		//Définit current à 0 s'il n'est pas défini.
		if(current == undefined) {
			current = 0 ;
		}

		//Stocke le tableau des images.
		this._images = images ;

		//Affiche l'image dont l'index est current.
		this._show(current) ;

	} ;

	//Méthodes privées

	/**
	 * Affiche l'image.
	 * @param current	(uin)	Index dans le tableau des images de l'image à afficher.
	 */
	ImagesZoomBox.prototype._show = function(current) {
		this._showing = true ;

		//Stocke l'index de l'image à afficher
		this._current = current ;

		//Désactive les boutons
		this._btPrevious.addClass("disabled") ;
		this._btPrevious[0].enabled = false ;
		this._btNext.addClass("disabled") ;
		this._btNext[0].enabled = false ;

		//Charge l'image
		this._imageLoader.attr("src", this._images[this._current].source) ;
	} ;

	/**
	 * Masque la lightbox.
	 */
	ImagesZoomBox.prototype._hide = function() {
		this._showing = false ;
		this._mask.hide() ;
		this._box.fadeOut(300) ;
	} ;

	//Gestion des évènements

	/**
	 * Passe à l'image précédente.
	 */
	ImagesZoomBox.prototype._previous = function(event) {
		//Si le bouton est désactivé, ne fait rien.
		if(!event.target.enabled) return ;
		this._show(this._current - 1) ;
	} ;

	/**
	 * Passe à l'image suivante.
	 */
	ImagesZoomBox.prototype._next = function(event) {
		//Si le bouton est désactivé, ne fait rien.
		if(!event.target.enabled) return ;
		this._show(this._current + 1) ;
	} ;

	/**
	 * Déclenché une fois l'image chargée.
	 */
	ImagesZoomBox.prototype._imgLoadHandler = function(event) {
		//Définit le titre de l'image et la source de l'image
		this._title.text(this._images[this._current].title) ;
		this._image.attr("src", this._images[this._current].source) ;
		this._image.attr("alt", this._images[this._current].title) ;

		//Détecte si l'image doit être redimensionnée
		//Afin qu'elle ne sorte pas de la zone d'affichage
		var newWidth = this._imageLoader[0].width ;
		var newHeight = this._imageLoader[0].height ;

		if(newWidth + 100 > $(window).width()) {
			newWidth = $(window).width() - 100 ;
			newHeight = Math.floor(newWidth * this._imageLoader[0].height / this._imageLoader[0].width) ;
		}

		if(newHeight + 100 > $(window).height()) {
			newHeight = $(window).height() - 100 ;
			newWidth = Math.floor(newHeight * this._imageLoader[0].width / this._imageLoader[0].height) ;
		}

		this._image.css({
			width: newWidth + "px",
			height: newHeight + "px"
		});

		//Active les boutons suivant et précédent en fonction de la position de l'image dans le tableau
		if(this._current == 0) {
			this._btPrevious.addClass("disabled") ;
			this._btPrevious[0].enabled = false ;
		}else{
			this._btPrevious.removeClass("disabled") ;
			this._btPrevious[0].enabled = true ;
		}

		if(this._current == this._images.length - 1) {
			this._btNext.addClass("disabled") ;
			this._btNext[0].enabled = false ;
		}else{
			this._btNext.removeClass("disabled") ;
			this._btNext[0].enabled = true ;
		}

		//Définit la taille du masque
		this._mask.css({
			width: $(document).width() + "px",
			height: $(document).height() + "px"
		}) ;

		//Positionne la lightbox
		this._box.css({
			"left": Math.floor(($(window).width() - this._box.innerWidth()) /2) + "px",
			"top": Math.floor(($(window).height() - this._box.innerHeight()) /2) + "px"
		}) ;

		//Affiche le masque et la lightbox.
		this._mask.show() ;
		this._box.fadeIn(300) ;

		//Vide le chargeur. Ce qui permet d'assurer que l'event load sur le chargeur d'images soit bien distribué.
		this._imageLoader.attr("src", "") ;
	} ;

	/**
	 * Controleur des zones de vignettes.
	 * Ce controleur recherche touts les images vignettes dans la zone spécifiée.
	 * Pour chaque vignette trouvées, ils stockes les informations sur l'image (source et titre)
	 * et ajout un écouteur d'évènement "click" sur le lien.
	 * @param	zone					(Objet jQuery)	Zone du DOM où sont affichées les vignettes.
	 * @param imagesZoomBox (Objet jQuery)	Lightbox à utiliser pour afficher les images zoomées.
	 */
	var MinViewer = function(zone, imagesZoomBox) {

		/**
		 * (Objet jQuery) Référence à la boite d'affichage de l'image zoomée.
		 */
		this._box = imagesZoomBox ;

		/**
		 * (Array) Liste des images.
		 */
		this._images = new Array() ;

		/**
		 * Constructeur
		 */

		//Ajoute un attribut indiquant que la zone a déjà été traitée
		$(zone).addClass("analyzed") ;

		//Recherche les images
		var aTags = $('a', zone) ;

		for(var i = 0 ; i < aTags.length ; i++) {
			var reg = /(.*)(-min)(\..*)$/ ;
			var regResult = reg.exec($('img', aTags[i]).attr("src")) ;
      if(regResult==null) continue;
			var image = new Object() ;
			image.source = regResult[1] + '-max.jpg' ;
			image.title = $("img", aTags[i]).attr("title") ;
			this._images.push(image) ;
			$(aTags[i]).bind("click", this, function(event){ event.data._imageClickHandler(event) }) ;
			$(aTags[i])[0].imgId = i ;
		}
	} ;

	// Gestion des évènements

	/**
	 * Déclenché lors d'un clique sur l'un des liens image.
	 * Désactive le fonctionnement par défaut du clique sur le lien et affiche l'image zoomée.
	 */
	MinViewer.prototype._imageClickHandler = function(event) {
		event.preventDefault() ;
		this._box.show(this._images, event.currentTarget.imgId) ;
	} ;


$(document).ready(miniatures) ;

function miniatures() {

	//Si un imagesZoomBox existe déjà, ne le recréé pas
	if(typeof(imagesZoomBox) == "undefined") {
		imagesZoomBox = new ImagesZoomBox() ;
	}

	var thumbs = $('.zoomimages:not(.analyzed)') ;

	for (var i=0; i < thumbs.length ; i++) {
		new MinViewer($(thumbs[i]), imagesZoomBox) ;
	}
} ;
