/**
 * @version 1.0
 *
 * @copyright Copyright 2009 WnG Solutions Sàrl, all rights reserved
 * @author Dorian Villet <dorian.villet AT wng DOT ch>
 * @package jtcamp
 */

/**
 * Création du plugin de gestion des étapes
 *
 * @internal Ce plugin est très lié au site et aux autres fichiers jQuery...
 *
 * - Exemples d'utilisations: 
 *
 * ####################
 * # 1. Etape définie #
 * ####################
 *
 * @param int currentStep Stocké dans un input de type hidden
 * @uses $(document).step();
 *
 *
 * ############################
 * # 2. Précédente / Suivante #
 * ############################
 *
 * @param string anchorID l'ID du lien changeant l'étape doit être "prev" ou "next"
 * @uses $('#prev, #next').live('click', function() { $(this).step(); return false; });
 */

/**
 * Gestion des étapes
 */
(function($) {
	
	// Variable de test
	var stepChanging = false;

	/**
	 * Gestion des étapes sur JTCamp
	 *
	 * @param function callback
	 * @return this
	 * @access public
	 */
    $.fn.step = function(callback) {

		/*
		 * CONFIGURATION
		 */

		// On prépare les paramètres par défaut des étapes
		var config = {
		
			// Nombre d'étapes
			nbSteps: 5,
			
			// Etape à charger (1 par défaut, au cas où)
			stepToLoad: 1,

			// On récupère le type d'utilisateur
			userType: $('#loginType').val() + 's',
			
			// Etape courante
			currentStep: 0,
			
			// Nouvelle étape
			newStep: 0,
			
			// Direction de la nouvelle étape (précédente / suivante)
			newStepDirection: $(this).attr('id')
		};
		
		
		/*
		 * GESTION DU PLUGIN
		 */
		
		// On vérifie si on est en plein changement de step
		if (isStepChanging()) return $(this);
		
		// On vérifie les formulaires
		if (!checkForms()) return $(this);
		
		// On met à jour
		updateStep();
		
		// On retourne l'élement pour ne pas briser la chaîne d'exécution jQuery
		return $(this);
		
		
		/*
		 * GESTION DES FORMULAIRES
		 */
		
		/**
		 * Vérifie les formulaires
		 *
		 * @param void
		 * @return boolean
		 */
		function checkForms() {
		
			// Si on a déjà définit la variable des formulaires, on continue
			if (forms.beforeIterator == 0) return true;
		
			// On sauve le contenu du formulaire modifié
			saveFormContent('after');
	
			// On vérifie que les deux tableaux ont des formulaires
			if (forms.afterIterator == 0) return false;
			
			// On compare les formulaires
			compareForms();
			
			// On compare les deux formulaires
			if (forms.errorsIterator != 0) {
			
				// On affiche la box
				displayFormsErrorBox();
				
				// On arrête l'update
				return false;
			}
			
			// Tout est okay
			return true;
		}
		
		/**
		 * Sauve les formulaires sérialisés
		 *
		 * @param string when
		 * @return void
		 */
		function saveFormContent(when) {
			
			// On boucle sur les formulaires
			$('.accordion form').each(function(i) {
				
				// On gère dans quel formulaire on doit sauver les données
				if (when == 'before') {
				
					// On ajoute l'élément avec l'ID en index
					forms.before[$(this).attr('id')] = $(this).serialize();
					
					// On incrémente
					forms.beforeIterator += 1;
					
				} else if (when == 'after') {
				
					// On ajoute l'élément avec l'ID en index
					forms.after[$(this).attr('id')] = $(this).serialize();
					
					// On incrémente
					forms.afterIterator += 1;
				}
			});
		}
		
		/**
		 * Compare les deux formulaires sérialisés
		 *
		 * @param void
		 * @return void
		 */
		function compareForms() {
		
			// On boucle sur les formulaires
			for (var i in forms.before) {
			
				// On vérifie que rien n'a changé
				if (forms.before[i] != forms.after[i]) {
						
					// On définit quel formulaire n'a pas été rempli correctement
					forms.errors.push(i);
					
					// On incrémente
					forms.errorsIterator += 1;
				}
			}
		}
		
		
		/*
		 * GESTION DES STEPS
		 */
		
		/**
		 * Définit si on est en changement d'état
		 *
		 * @param void
		 * @return void
		 */
		function isStepChanging() {
		
			// On est entrain de changer
			if (stepChanging == true) return true;
			
			// On change
			stepChanging = true;
				
			// On continue le script
			return false;
		}
		
		/**
		 * Changement d'étape
		 *
		 * @param void
		 * @return void
		 */
		function updateStep() {
			
			// On définit la nouvelle étape
			if (!setNewStep()) return false;
			
			// On affiche / cache les contenus
			$('#' + config.userType + '_campkits_step' + config.currentStep + '_refresh').fadeOut('slow', function() {
				
				// On met à jour la navigation
				updateStepsIndicator();
				updateStepsNavigationLinks();
			
				// On cache et vide toutes les zones de contenus
				dumpStepsContainers();
				
				// On charge le nouveau contenu
				loadContent(config.userType + '_campkits_step' + config.stepToLoad + '_refresh', function() {
				
					// On active le traitement des select
					$('.accordion form select').change(function() { enableSaveButton(this); });
				
					// On remet à zéro
					if (forms.beforeIterator != 0 && forms.afterIterator != 0) {
						
						// Formulaires par défaut
						forms = getDefaultFormsValues();
					}
				
					// On sauve le contenu des formulaires afin de vérifier les modifications par la suite
					saveFormContent('before');
					
					// On remet la nouvelle étape à zéro
					config.newStep = 0;
			
					// On s'assure que la navigation sera débloquée... au cas où l'utilisateur va trop vite
					stepChanging = false;
					
					// On effectue le callback
					if (typeof(callback) == 'function') callback();
					
					// On gère les exceptions (codes à charger après l'exécution du plugin pour des raisons d'actualisation du DOM)
					ajaxReadyCallbacks();
				});
			});
		}
		
		/**
		 * Définit la nouvelle étape
		 *
		 * @param void
		 * @return void
		 */
		function setNewStep() {
		
			// On définit l'étape courante
			config.currentStep = parseInt($('#' + config.userType + '_campkits_step').val(), 10);
				
			// On vérifie que l'étape courante est dans une tranche correcte
			if (config.currentStep < 1 || config.currentStep > config.nbSteps) return false;
		
			// On s'assure qu'on a bien cliqué sur un lien avec une config.newStepDirection
			if (config.newStepDirection == 'prev' || config.newStepDirection == 'next') {
	
				// Sécurité
				if (config.newStepDirection == 'prev' && config.currentStep == 1) return false;
				if (config.newStepDirection == 'next' && config.currentStep == config.nbSteps) return false;
		
				// On prépare la nouvelle étape
				config.newStep = (config.newStepDirection == 'prev') ? config.currentStep - 1 : config.currentStep + 1;
				
			} else if (config.newStepDirection == 'finalize') {
				
				// On affiche la box de confirmation de dernière étape
				displayLastStepBox();
				
				// On annule le changement de step
				return false;
			}
		
			// On met à jour le champ caché
			if (config.newStep > 0) $('#' + config.userType + '_campkits_step').val(config.newStep);
			
			// On définit quelle est l'étape à charger
			config.stepToLoad = (config.newStep > 0) ? config.newStep : config.currentStep;
			
			// Tout est okay
			return true;
		}
		
		/**
		 * On boucle sur toutes les zones de contenus, et on les cache/vide
		 *
		 * @param void
		 * @return void
		 */
		function dumpStepsContainers() {
			$('.refreshZone').each(function() {
				$(this).html('').hide();
			});
		}
		
		/**
		 * On met à jour la navigation des étapes
		 *
		 * @param void
		 * @return void
		 */
		function updateStepsIndicator() {
		
			// On supprime toutes les classes actives
			$('#steps li').each(function() {
				$(this).removeClass('active');
			});
	
			// On met à jour la liste des étapes
			$('#steps li.step' + config.stepToLoad).addClass('active');
		}
		
		/**
		 * On met à jour les liens de navigation des étapes
		 *
		 * @param void
		 * @return void
		 */
		function updateStepsNavigationLinks() {
		
			// Vitesse de l'animation
			var animationSpeed = 'slow';
		
			// Step 1
			if (config.currentStep == 1 && config.newStep == 0)	$('#prev').fadeOut(animationSpeed);
			
			// Step 5
			else if (config.currentStep == 5 && config.newStep == 0) $('#next').fadeOut(animationSpeed);

			// Step 1 à 2
			else if (config.currentStep == 1 && config.newStep == 2) $('#prev').fadeIn(animationSpeed);
			
			// Step 2 à 1
			else if (config.currentStep == 2 && config.newStep == 1) $('#prev').fadeOut(animationSpeed);
			
			// Step 4 à 5
			else if (config.currentStep == 4 && config.newStep == 5) $('#next').fadeOut(animationSpeed, function() { $('#finalize').fadeIn(animationSpeed); });
			
			// Step 5 à 4
			else if (config.currentStep == 5 && config.newStep == 4) $('#finalize').fadeOut(animationSpeed, function() { $('#next').fadeIn(animationSpeed); });
		}
		
		
		/*
		 * CALLBACKS
		 */
		
		/**
		 * Codes à charger après l'exécution du plugin pour des raisons d'actualisation du DOM
		 *
		 * @param void
		 * @return void
		 */
		function ajaxReadyCallbacks() {
		
			// Gestion de l'upload de document médical à la 3ème étape
			if (config.stepToLoad == 3) {
			
				// Nom du champ hidden
				var hiddenFieldName = 'medical_form';
			
				// On boucle sur tous les champs hidden
				$('input[type=hidden][name=' + hiddenFieldName + ']').each(function() {
				
					// Attention au nombre d'underscore dans le nom de l'input !
					var accordion = $(this).attr('id').split('_')[2];
					
					// Chargement de la classe d'upload
					new Ajax_upload('uploadMedical_' + accordion, {
						action: 'ajax/upload_medical_form.ajax.php',
						name: 'upload',
						onSubmit: function(file, extension) {
							this.setData({
								idCamper: $('#idCamper_' + accordion).val()
							});
						},
						onComplete: function(file, xml) {
					
							// On cache les notifications
							$('#uploadMedicalResult_' + accordion).fadeOut();
							
							// On met à jour les notifications
							updateNotification(xml, 'uploadMedicalResult_' + accordion);
							
							// On sauve dans un champ hidden pour l'insertion SQL
							$('#' + hiddenFieldName + '_' + accordion).val($(xml).find('file').text());
						}
					});
				});
			}
		}
		
		
		/*
		 * GESTION DES BOXES
		 */
		
		/**
		 * Affiche la box avec les erreurs
		 *
		 * @param void
		 * @return void
		 */
		function displayFormsErrorBox() {
	
			// Informations diverses
			var text = 'You haven\'t saved the information about those campers: ';
			var text2 = 'Do you want to continue without saving ?';
			
			// Variable de test
			var boolTest = true;
			
			// On ajoute le nom des campeurs
			for (var i in forms.errors) {
			
				// On split l'ID
				var splittedID = forms.errors[i].split('_');
			
				// On récupère le nom de l'enfant
				var camperName = '<strong>' + $('.accordion #' + splittedID[0] + '_' + splittedID[1] + ' h3').html() + '</strong>';
				
				// On gère les virgules
				if (boolTest) {
					text += camperName;
					
					// On remet le test à false
					boolTest = false;
					
				} else {
				
					// On écrit avec la virgule
					text += ', ' + camperName;
				}
			}
			
			// On termine le texte
			text += '.';
			
			// On ajoute le contenu
			$('#contentModal')
				.dialog({
					title: 'Confirmation',
					width: 700,
					modal: true,
					show: 'blind',
					hide: 'blind',
					draggable: false,
					resizable: false,
					closeOnEscape: false,
					position: defaultContentModalPositions,
					buttons: {
						'Go back': function() {
							
							// On remet les erreurs des formulaires à zéro
							forms = resetFormsValues(forms, 'after');
			
							// On s'assure que la navigation sera débloquée... au cas où l'utilisateur va trop vite
							stepChanging = false;
						
							// On ferme la box
							defaultContentModalCloseButton();
						},
						'Confirm': function() {
							
							// On ferme la box
							defaultContentModalCloseButton();
							
							// On met à jour l'étape ou on affiche la dernière box
							if (config.newStepDirection == 'finalize') {
								displayLastStepBox();
							} else {
								updateStep();
							}
						}
					}
				})
				.append($('<ul></ul>')
					.addClass('notification')
					.html($('<li></li>')
						.addClass('info')
						.html(text)
					)
					.append($('<li></li>')
						.addClass('help')
						.html(text2)
					)
				)
				.dialog('open');
		}
		
		/**
		 * Affiche la box de confirmation de dernière étape
		 *
		 * @param void
		 * @return void
		 */
		function displayLastStepBox() {
	
			// Informations diverses
			var link = $('#stepsNavigation #finalize').attr('href');
			var text = 'You have finished to update your camper\'s campkits. We will now redirect you to your personal home space.';
			
			// On prépare les boutons
			var saveButton = function() { window.open(link, '_self'); };
			
			// On ajoute le contenu
			$('#contentModal')
				.dialog({
					title: 'Finalize updates / booking',
					width: 700,
					modal: true,
					show: 'blind',
					hide: 'blind',
					draggable: false,
					resizable: false,
					closeOnEscape: false,
					position: defaultContentModalPositions,
					buttons: { 'Go back': defaultContentModalCloseButton, 'Confirm': saveButton }
				})
				.append($('<p></p>')
					.addClass('icon info')
					.html(text)
				)
				.dialog('open');
		}
	}
})(jQuery);