if(typeof console == "undefined") {
	console = {log: function(){}, dir: function(){}};	
}

tx_decadvforms_validation = function() {
	return this;
}

tx_decadvforms_validation.prototype = {	
	
	formId: '',
	AJAXURL: '',
	config: [],
	submitFuncParts: [],
	
	fieldContainerSelector: ".dec-advforms-field",
	errorMessageContainerSelector: ".dec-advforms-error",
	
	singleFieldValidation: false,
	submitValidation: false,
	
	fieldsInError: [],
	AJAXerrors: [],
	
	LL: {},

	/**
	  * Exécuté lorsque la valeur d'un champ a été validée (à redéfinir éventuellement via jQuery.extend())
	  *
	**/
	fieldValidated: function(field, options) {
		var error_field = options.altErrorFieldSelector ? jQuery(options.altErrorFieldSelector).parents(this.fieldContainerSelector).find(this.errorMessageContainerSelector) : field.parents(this.fieldContainerSelector).find(this.errorMessageContainerSelector);
		if(error_field.text() == eval(options.error_message)) error_field.text("")
		error_field.hide();
	},
	
	
	/**
	  * Exécuté lorsque la valeur d'un champ a été invalidée (à redéfinir éventuellement via jQuery.extend())
	  *
	**/
	fieldInvalidated: function(field, options) {
		var error_field = options.altErrorFieldSelector ? jQuery(options.altErrorFieldSelector).parents(this.fieldContainerSelector).find(this.errorMessageContainerSelector) : field.parents(this.fieldContainerSelector).find(this.errorMessageContainerSelector);
		error_field.text(eval(options.error_message)).show();
	},
	
	
	/**
	  * Exécuté à la fin de l'évènement onSubmit du formulaire (à redéfinir éventuellement via jQuery.extend())
	  *
	**/
	onSubmitEvent: function(ok) {

	},
	
	triggers: {
		input: "blur",
		text: "blur",
		password: "blur",
		select: "change",
		checkbox: "click",
		checkboxes: "click",
		radio: "click",
		yesno: null,
		upload: null,
		date: null
	},
	
	valueGetters: {
		input: "jQuery(###OBJ###).val()",
		text: "jQuery(###OBJ###).val()",
		password: "jQuery(###OBJ###).val()",
		select: "jQuery(###OBJ###).val()",
		checkbox: "###OBJ###.checked",
		checkboxes: '(function(obj){\
					var arr = [];\
					jQuery(obj).parents("###CONTAINER###").find("input[type=checkbox]").each(function(){\
						if(this.checked) arr.push(jQuery(this).val());\
					});\
					return arr;\
				})(###OBJ###);',
		radio: '(function(obj){\
					var val = "";\
					jQuery(obj).parents("###CONTAINER###").find("input[type=radio]").each(function(){\
						if(jQuery(this).attr("name") == jQuery(obj).attr("name") && this.checked) val = jQuery(this).val();\
					});\
					return val;\
				})(###OBJ###);',
		yesno: '(function(obj){\
					var arr = [];\
					jQuery(obj).parents("###CONTAINER###").find("input[type=radio]").each(function(){\
						if(this.checked) arr.push(jQuery(this).val());\
					});\
					return arr;\
				})(###OBJ###);',
		upload: "jQuery(###OBJ###).val()",
		date: '(function(obj){\
					var arr = [];\
					jQuery(obj).parents("###CONTAINER###").find(":input").each(function(){\
						if(jQuery(this).attr("id").substr(-2) == "-d") arr[0] = jQuery(this).val();\
						if(jQuery(this).attr("id").substr(-2) == "-m") arr[1] = jQuery(this).val();\
						if(jQuery(this).attr("id").substr(-2) == "-y") arr[2] = jQuery(this).val();\
					});\
					return arr;\
				})(###OBJ###);'
	},
	

	/**
	  * Lit la configuration de la validation du formulaire et crée les évènements correspondant
	  *
	**/
	init: function(formId, data, LLdata) {
		this.formId = formId;
		var txt = '';
		this.config = jQuery.parseJSON(data);
		this.LL = jQuery.parseJSON(LLdata);
		
		jQuery("#" + this.formId + " " + this.errorMessageContainerSelector).hide();
		
		for(i = 0; i < this.config.length; i++) {
			//vérifications relatives au type de champ
			var typereq = this['typecheck_' + this.config[i].fieldType + '_required'] && this.hasSpecificValidation(this.config[i].validations, 'required');
			if(this.submitValidation && (this['typecheck_' + this.config[i].fieldType] || typereq)) {
				
				var funcPart = typereq ? this.config[i].fieldType + '_required' : this.config[i].fieldType;
				var val = this.valueGetters[this.config[i].fieldType] ? this.valueGetters[this.config[i].fieldType].replace(/###OBJ###/g, 'this').replace(/###CONTAINER###/g, this.fieldContainerSelector) : '';

				this.submitFuncParts.push({
					id: this.config[i].fieldSelector.replace(/[^a-zA-Z0-9]/g, '_'),
					func: '\
					  (function(){\
							var field = jQuery("' + this.config[i].fieldSelector + '");\
							var value = "";\
							field.each(function(){ value = ' + val + '});\
							var options = {error_message: "' + this.LL['typeerror_' + funcPart] + '"};\
							var ok = validator.typecheck_' + funcPart + '(field, value, options);\
							if(ok){\
								validator.fieldValidated(field, options);\
							} else validator.fieldInvalidated(field, options);\
							\
							return ok;\
						})();\
				  '});
			}
			
				//ajout des validations configurées
			for(j = 0; j < this.config[i].validations.length; j++) {
				txt += 'add ' + this.config[i].validations[j].type + ' to ' + this.config[i].fieldSelector + "\n";
				this.addValidation(this.config[i].fieldName, this.config[i].fieldSelector, this.config[i].fieldType, this.config[i].validations[j].type, this.config[i].validations[j]);
			}
		}
		
//		console.dir(this.submitFuncParts);
		
			//validation onsubmit
		if(this.submitFuncParts.length > 0) {
			var validator = this;
			jQuery("#" + this.formId).submit(function() {
				validator.fieldsInError = validator.AJAXerrors;
				var formok = validator.fieldsInError.length == 0;
				for(var i = 0; i < validator.submitFuncParts.length; i++) {
					if(jQuery.inArray(validator.submitFuncParts[i].id, validator.fieldsInError) == -1 && !eval(validator.submitFuncParts[i].func)) {
						validator.fieldsInError.push(validator.submitFuncParts[i].id);
						formok = false;
					}
				}
				validator.onSubmitEvent(formok);
				
//				console.log(formok);
				return formok;
			});
		}
	},
	

	/**
	  * Ajoute un évènement de validation à un champ
	  *
	**/
	addValidation: function(fieldName, fieldSelector, type, validationType, options) {
		var field = jQuery(fieldSelector);
		var trigger = this.triggers[type] ? this.triggers[type] : null;
		var val = this.valueGetters[type] ? this.valueGetters[type].replace(/###OBJ###/g, 'this').replace(/###CONTAINER###/g, this.fieldContainerSelector) : '';
		var fieldId = fieldSelector.replace(/[^a-zA-Z0-9]/g, '_');
		
		if(this.singleFieldValidation && trigger) {
			var validator = this;
			field.bind(trigger, function(e) {
				if(validator["validation_" + validationType]) {
					var value = eval(val);
					var ok = validator["validation_" + validationType](field, value, options);
					if(ok) {
						validator.fieldValidated(field, options);
					} else validator.fieldInvalidated(field, options);
				} else if(validator.AJAXURL) {
					//AJAX validation
					var params = {};
					params['tx_decadvforms_pi1[validField]'] = fieldName;
					params['tx_decadvforms_pi1[validType]'] = validationType;
					
					jQuery("#" + validator.formId + " :input").each(function(){
						params[jQuery(this).attr("name")] = jQuery(this).val();
					});
					
					jQuery.getJSON(validator.AJAXURL, params, function(data) {
						if(data.ok) {
							validator.fieldValidated(field, options);
								//on supprime le champ du tableau des erreurs AJAX
							var offset = jQuery.inArray(fieldId, validator.AJAXerrors);
							if(offset != -1) validator.AJAXerrors.splice(offset, 1);
						} else {
							validator.fieldInvalidated(field, options);
								//on stocke l'erreur pour bloquer la validation du formulaire
							if(jQuery.inArray(fieldId, validator.AJAXerrors) == -1) validator.AJAXerrors.push(fieldId);
						}
					});
				}
			});
		}
		
		if(this.submitValidation && this["validation_" + validationType]) {
			this.submitFuncParts.push({
				id: fieldId,
				func: '\
				  (function(){\
						var field = jQuery("' + fieldSelector + '");\
						var value = "";\
						field.each(function(){ value = ' + val + '});\
						var options = jQuery.parseJSON(\'' + jQuery.toJSON(options) + '\');\
						var ok = validator.validation_' + validationType+'(field, value, options);\
						if(ok){\
							validator.fieldValidated(field, options);\
						} else validator.fieldInvalidated(field, options);\
						\
						return ok;\
					})();\
			  '});
		}
	},
	


	
	
	
	
	/********************************************* Validation Functions *****************************************/
	
	validation_required: function(field, value, options) {
		return (typeof(value) == typeof([]) && value.length > 0) || (value != '' && value != 0 && value != false);
	},
	
	validation_int: function(field, value, options) {
		return value == '' || parseInt(value).toString() == value;
	},
	
	validation_numeric: function(field, value, options) {
		var pat1 = new RegExp("^[+-]?[0-9]+\.?[0-9]*([e|E][0-9]+)?$", 'g');
		var pat2 = new RegExp("^0x[0-9A-Fa-f]+$", 'g');
		return value == '' || pat1.test(value) || pat2.test(value);
	},
	
	validation_alpha: function(field, value, options) {
		var pat = new RegExp("^[a-zA-Z|\s]*$", 'g');
		return value == '' || pat.test(value);
	},
	
	validation_alphanum: function(field, value, options) {
		var pat = new RegExp("^[a-zA-Z0-9|\\s]*$", 'g');
		return value == '' || pat.test(value);
	},
	
	validation_alphanum_x: function(field, value, options) {
		var pat = new RegExp("^[a-zA-Z0-9|\\-|_|\\s]*$", 'g');
		return value == '' || pat.test(value);
	},
	
	validation_atleast: function(field, value, options) {
		return value == '' || parseFloat(value) >= parseFloat(options.val);
	},
	
	validation_atmost: function(field, value, options) {
		return value == '' || parseFloat(value) <= parseFloat(options.val);
	},
	
	validation_minchars: function(field, value, options) {
		return value == '' || value.length >= parseInt(options.val);
	},
	
	validation_maxchars: function(field, value, options) {
		return value == '' || value.length <= parseInt(options.val);
	},
	
	validation_regex: function(field, value, options) {
		var pat = new RegExp(options.regex.substring(1, options.regex.length-1).replace(/\|\*\|/g, '\\'), 'gi');
		return value == '' || pat.test(value);
	},
	
	validation_email: function(field, value, options) {
		var pat = new RegExp("^[^@\\s]+@[^@\\s]+\.[a-z]{2,4}$", 'g');
		return value == '' || pat.test(value.toLowerCase());
	},
	
	validation_twice: function(field, value, options) {
		var origval = eval(this.valueGetters[options.fieldType].replace(/###OBJ###/g, 'jQuery("'+options.originalSelector+'").get(0)').replace(/###CONTAINER###/g, this.fieldContainerSelector));
		return value == origval;
	},
	
	/********************************************* Type validation Functions *****************************************/
	
	typecheck_date: function(field, value, options) {
		if(typeof(value) != typeof([]) || value.length != 3) return false;
		var dt = new Date(value[2], value[1]-1, value[0]);
		return (value[0] == 0 && value[1] == 0 && value[2] == 0) || (value[0] == dt.getDate() && value[1]-1 == dt.getMonth() && value[2] == dt.getFullYear());
	},
	
	typecheck_date_required: function(field, value, options) {
		if(typeof(value) != typeof([]) || value.length != 3) return false;
		var dt = new Date(value[2], value[1]-1, value[0]);
		return value[0] == dt.getDate() && value[1]-1 == dt.getMonth() && value[2] == dt.getFullYear();
	},
	
	typecheck_yesno_required: function(field, value, options) {
		if(typeof(value) != typeof([])) return false;
		return value.length == field.length / 2;
	},
	
	
	
	
	
	
	
	
	
	
	
	/********************************************* Misc *****************************************/
	
	hasSpecificValidation: function(validations, type) {
		for(var i = 0; i < validations.length; i++) {
			if(validations[i].type == type) return true;
		}
		
		return false;
	}
};