/**
 * @copyright Copyright 2008-2009 WnG Solutions Sàrl, all rights reserved
 * @author Daniel Calderini <daniel.calderini [AT] wng [DOT] ch>
 * @package WnG Datatrans
 *
 * @filename action.js
 * @version 1.2.0
 * @date 2009-08-05
 */

/**
 * Gestion du formulaire d'abonnement
 */
wng_datatrans = {
	// Liste et configuration des cases à cocher
	checkboxes: new Array(),
	
	// Les types d'offres principales
	subscriptionTypesMain: new Array(),
	
	// Les types d'offres secondaires
	subscriptionTypesSub: new Array(),
	
	// Liste des textes à afficher selon l'offre choisie
	subscriptionTexts: new Array(),
	
	// Identifiants des champ pour stocker le prix
	priceField: '',
	priceFieldDisplay: '',
	
	// Valeurs par défaut pour le prix
	defaultPrice: 0,
	defaultPriceDisplay: '',
	
	/**
	 * Initialiation du formulaire de choix d'abonnement
	 *
	 * @return void
	 */
	init: function() {
		$('#noJSzone').addClass('hideMe');
		$('#checkboxesZone').removeClass('hideMe');
		
		// Ajout des actions sur les checkboxes
		wng_datatrans.addOnclickAction();
		
		// Initialisation des différentes checkboxes
		for (var i in wng_datatrans.checkboxes) {
			if (wng_datatrans.checkboxes[i]['disabled'] && wng_datatrans.checkboxes[i]['disabled'] == 1) {
				$('#' + wng_datatrans.checkboxes[i]['name']).attr('disabled', true);
			}
		}
	},
	
	/**
	 * Action principale, appelée lorsque l'utilisateur coche/décoche une case
	 * Ne doit pas être appelée récursivement
	 *
	 * @param mixed currentObjText 
	 * @return void
	 */
	actionCheckbox: function() {
		// Appel de la fonction "recursive safe"...
		wng_datatrans.actionCheckboxRecursive(this);
		
		// Mise à jour de l'affichage
		wng_datatrans.updateDisplay();
	},
	
	/**
	 * Action principale (2). Cette méthode peut être appelée récursivement (mise à jour de plusieurs cases)
	 *
	 * @param string currentObjText Ce texte peut être utilisé avec jQuery ($(...)) pour accéder à la case à cocher courrante
	 * @return void
	 */
	actionCheckboxRecursive: function(currentObjText) {
		var currentObj = $(currentObjText);
		var id = currentObj.attr('value');
		
		// Action "onCheck"
		if (currentObj.attr('checked') && wng_datatrans.checkboxes[id]['onCheck'])
			wng_datatrans.execActions(wng_datatrans.checkboxes[id]['onCheck']);
		
		// Action "onUncheck"
		if (!currentObj.attr('checked') && wng_datatrans.checkboxes[id]['onUncheck'])
			wng_datatrans.execActions(wng_datatrans.checkboxes[id]['onUncheck']);
		
		// Gestion du prix
		if (wng_datatrans.checkboxes[id]['price']) {
			if (currentObj.attr('checked'))
				wng_datatrans.updatePrice(wng_datatrans.checkboxes[id]['price']['value'], wng_datatrans.checkboxes[id]['price']['display']);
			else
				wng_datatrans.updatePrice(wng_datatrans.defaultPrice, wng_datatrans.defaultPriceDisplay);
		}
	},
	
	/**
	 * Fonction qui ajoute la fonction onclick aux différentes cases à cocher
	 *
	 * @return void
	 */
	addOnclickAction: function() {
		for (var i in wng_datatrans.checkboxes) {
			$('#' + wng_datatrans.checkboxes[i]['name']).click(wng_datatrans.actionCheckbox);
		}
	},
	
	/**
	 * Exécute les actions associées à la case qui a été cochée/décochée
	 *
	 * @param array actions
	 * @return void
	 */
	execActions: function(actions) {
		// Liste des checkboxes
		for (var actionType in actions) {
			for (var i in actions[actionType]) {
				// On ne travaille que sur les identifiants des checkboxes, pas sur les paramètres
				if (wng_datatrans.is_numeric(i)) {
					var field = actions[actionType][i];
					// Paramètre: condition
					if (actions[actionType]['if'] && actions[actionType]['if'][field]) {
						if (!wng_datatrans.execIfActions(actions[actionType]['if'][field]))
							continue;
					}
					
					// Récusivité des appels
					if (actions[actionType]['notRecursive'] && actions[actionType]['notRecursive'][i] && actions[actionType]['notRecursive'][i] == 1)
						var notRecursive = true;
					else
						var notRecursive = false;
					
					switch (actionType) {
						case 'check':
							wng_datatrans.actionCheck(actions[actionType][i], notRecursive);
						break;
						
						case 'uncheck':
							wng_datatrans.actionUncheck(actions[actionType][i], notRecursive);
						break;
						
						case 'activate':
							wng_datatrans.actionActivate(actions[actionType][i]);
						break;
						
						case 'deactivate':
							wng_datatrans.actionDeactivate(actions[actionType][i]);
						break;
					}
				}
			}
		}
	},
	
	/**
	 * Parse une condition (if) associée à une action et retourne si la condition est vérifiée
	 *
	 * @param array actions
	 * @return bool
	 */
	execIfActions: function(actions) {
		for (var i in actions) {
			for (var j = 0; j < actions[i].length; j++) {
				switch (i) {
					case 'checked':
						if (!$('#' + wng_datatrans.checkboxes[actions[i][j]]['name']).attr('checked'))
							return false;
					break;
					
					case 'unchecked':
						if ($('#' + wng_datatrans.checkboxes[actions[i][j]]['name']).attr('checked'))
							return false;
					break;
					
					case 'activated':
						if ($('#' + wng_datatrans.checkboxes[actions[i][j]]['name']).attr('disabled'))
							return false;
					break;
					
					case 'deactivated':
						if (!$('#' + wng_datatrans.checkboxes[actions[i][j]]['name']).attr('disabled'))
							return false;
					break;
				}
			}
		}
		
		return true;
	},
	
	/**
	 * Action: cocher une case
	 *
	 * Les actions associées à la case qui sera cochée sont exécutées
	 *
	 * @param int id
	 * @return void
	 */
	actionCheck: function(id, notRecursive) {
		var checkName = wng_datatrans.checkboxes[id]['name'];
		
		if ($('#' + checkName).attr('checked'))
			return;
		
		$('#' + checkName).attr('checked', true);
		
		if (!notRecursive)
			wng_datatrans.actionCheckboxRecursive('#' + checkName);
	},
	
	/**
	 * Action: décocher une case
	 *
	 * Les actions associées à la case qui sera décochée sont exécutées
	 *
	 * @param int id
	 * @return void
	 */
	actionUncheck: function(id, notRecursive) {
		var checkName = wng_datatrans.checkboxes[id]['name'];
		
		if (!$('#' + checkName).attr('checked'))
			return;
		
		$('#' + checkName).attr('checked', false);
		
		if (!notRecursive)
			wng_datatrans.actionCheckboxRecursive('#' + checkName);
	},
	
	/**
	 * Action: active une case (disabled=false)
	 *
	 * @param int id
	 * @return void
	 */
	actionActivate: function(id) {
		var checkName = wng_datatrans.checkboxes[id]['name'];
		$('#' + checkName).attr('disabled', false);
	},
	
	/**
	 * Action: désactive une case (disabled=true)
	 *
	 * @param int id
	 * @return void
	 */
	actionDeactivate: function(id) {
		var checkName = wng_datatrans.checkboxes[id]['name'];
		$('#' + checkName).attr('disabled', true);
	},
	
	/**
	 * Mise à jour de l'affichage.
	 *
	 * - Met à jour le prix
	 * - Affiche le texte de description de l'offre
	 * - Sélectionne l'offre dans la liste déroulante
	 *
	 * @return void
	 */
	updateDisplay: function() {
		var total = 0;
		var price = new Array(
			wng_datatrans.defaultPrice,
			wng_datatrans.defaultPriceDisplay
		);
		
		// On parcours les checkboxes pour voir lesquelles ont été cochées
		for (var i in wng_datatrans.checkboxes) {
			if ($('#' + wng_datatrans.checkboxes[i]['name']).attr('checked')) {
				total += parseInt(i);
				
				if (wng_datatrans.checkboxes[i]['price']) {
					price[0] = parseInt(price[0]) + parseInt(wng_datatrans.checkboxes[i]['price']['value']);
					price[1] = wng_datatrans.checkboxes[i]['price']['display'];
				}
			}
		}
		
		// Mise à jour du prix
		wng_datatrans.updatePrice(price);
		
		// Mise à jour du texte affiché
		wng_datatrans.updateTextDisplay(total);
		
		// Mise à jour de la liste déroulante (c'est cette valeur qui est reprise)
		wng_datatrans.updateSelectBox(total);
	},
	
	/**
	 * Met à jour la valeur sélectionnée dans la liste déroulante
	 *
	 * @param int newOfferId Identifiant de la nouvelle offre sélectionnée
	 * @return void
	 */
	updateSelectBox: function(newOfferId) {
		if (newOfferId == 0)
			newOfferId = -1;
		
		$('#tx_wngdatatrans_pi1_subscriptionType option[value=\'' + newOfferId + '\']').attr('selected', true);
	},
	
	/**
	 * Met à jour le prix (dans le champ ainsi que celui affiché)
	 *
	 * @param array price L'index 0 est le prix à placer dans le champ, l'index 1 celui à afficher
	 * @return void
	 */
	updatePrice: function(price) {
		$('#' + wng_datatrans.priceField).attr('value', price[0]);
		$('#' + wng_datatrans.priceFieldDisplay).html(price[1]);
	},
	
	/**
	 * Met à jour le texte de description de l'offre sélectionnée
	 *
	 * @param int total Identifiant de l'offre
	 * @return void
	 */
	updateTextDisplay: function(total) {
		var texts;
		
		if (total == 0) {
			$('#subscriptionTypeList').html('');
			return;
		}
		
		// Recherche dans le tableau principal
		if (!wng_datatrans.subscriptionTypesMain[total]) {
			wng_datatrans.searchSubTexts(total);
		}
		
		// Reprise du texte
		texts = wng_datatrans.getTexts(wng_datatrans.subscriptionTypesMain[total]);
		
		$('#subscriptionTypeList').html(texts);
	},
	
	/**
	 * Génère le texte de l'offre à partir des identifiant trouvé, correspondant au identifiant du tableau subscriptionTexts
	 *
	 * @param array texts Liste des textes à afficher
	 * @return string
	 */
	getTexts: function(texts) {
		var content = '';
		
		if (!texts)
			return content;
		
		for (var i = 0; i < texts.length; i++) {
			content += wng_datatrans.subscriptionTexts[texts[i]];
		}
		
		return content;
	},
	
	/**
	 * Recherche, pour un total donné, quelle sous-offre a été sélectionnée
	 *
	 * @param int total
	 * @return array Un tableau contenant la liste des nouveaux textes à afficher
	 */
	searchSubTexts: function(total) {
		var baseValue = 0;
		var index = 0;
		
		// Recherche de la valeur, dans le tableau secondaire, qui se rapproche le plus de l'abonnement choisi
		for (var i in wng_datatrans.subscriptionTypesSub) {
			var addToValue = parseInt(wng_datatrans.subscriptionTypesSub[i]['addToValue']);
			
			if (addToValue < total && addToValue > baseValue) {
				baseValue = addToValue;
				index = i;
			}
		}
		
		if (wng_datatrans.subscriptionTypesMain[total - baseValue]) {
			var newArray = wng_datatrans.array_merge(
				wng_datatrans.subscriptionTypesMain[total - baseValue],
				wng_datatrans.subscriptionTypesSub[index]['addToTexts']
			);
		} else {
			var newArray = wng_datatrans.searchSubTexts(total - baseValue);
			var newArray = wng_datatrans.array_merge(newArray, wng_datatrans.subscriptionTypesSub[index]['addToTexts']);
		}
		
		wng_datatrans.subscriptionTypesMain[total] = newArray;
		return newArray;
	},
	
	/**
	 * Méthode identique à la fonction PHP is_numeric
	 *
	 * @param mixed value
	 * @return bool
	 */
	is_numeric: function(value) {
		var allowedChars = '0123456789.';
		var isNumber = true;
		var char;
		
		for (var i = 0; i < value.length && isNumber == true; i++) { 
			char = value.charAt(i); 
			if (allowedChars.indexOf(char) == -1)
				isNumber = false;
		}
		
		return isNumber;
	},
	
	/**
	 * Méthode identique à la fonction PHP array_merge
	 *
	 * @param array array1
	 * @param array array2
	 * @return array
	 */
	array_merge: function(array1, array2) {
		return array1.concat(array2);
	}
};

$(document).ready(function() {
	//
	wng_datatrans.init();
});