(function($){
	/**
		Le principe du FieldValidator est simple:
		- Il analyse automatiquement tous les champs ayant des classes 'validator_*' (si g�r�es par les validateurs existants) :
			- Si le champ est valide, le FieldValidator supprime l'�ventuelle classe fieldInvalid et d�clenche un �v�nement 'validator:fieldIsValid' sur le champ
			- Si le champ est invalide, le FieldValidator met une classe fieldInvalid et d�clenche un �v�nement 'validator:fieldIsInvalid'
	*/
	FieldValidator = {
		validators: {
			required: {
				selector: '.validator_required',
				errorMessage: 'Obligatoire',
				validate: function(field, validatorOptions){
					switch( field.type ){
						case 'checkbox':
						case 'radio':
							return jQuery('input[name="' + field.name + '"]:checked').length > 0;
						default:
							return jQuery.trim( $(field).val() ) != '';
					}

				}
			},
			ajax: {
				selector: '.validator_ajax',
				validate: function(field, validatorOptions){
					return false;
				}
			},

			required_min: {
				selectorMotif: /validator_required_min_(\d+)/,
				errorMessage: '$1 centre(s) d\'int&eacute;r&ecirc;t minimum',
				validate: function(field, validatorOptions){
					var fClass = this.getSelectorMotifFieldClass(field, validatorOptions.selectorMotif);
					var minLength = fClass.replace( new RegExp(validatorOptions.selectorMotif), '$1' );

					// pour compa market et media
					// TODO : Trouver une meilleur solution;
					return $(':input[class*="validator_required_min_3"]:checked').length >= minLength;
					//return $(':input[name="' + field.name + '"]:checked').length >= minLength;
				}
			},
			equals_to_field: {
				selectorMotif: /validator_password_equals_to_field_([^ ]*)/,
				errorMessage: 'Mots de passe non identiques',
				validate: function(field, validatorOptions){
					var fClass = this.getSelectorMotifFieldClass(field, validatorOptions.selectorMotif);
					var otherFieldId = fClass.replace( new RegExp(validatorOptions.selectorMotif), '$1' );
					var samePasswords = ( $(field).val() == $('#' + otherFieldId).val() );
					if( samePasswords ){
						$('#' + otherFieldId).removeClass('fieldInvalid').trigger('validator:fieldIsValid');
					}else{
						$('#' + otherFieldId).addClass('fieldInvalid').trigger('validator:fieldIsInvalid');
					}
					return samePasswords;
				}
			},
			min_length: {
				selectorMotif: /validator_min_length_(\d+)/,
				errorMessage: 'Ce champ doit comporter au moins $1 caract&egrave;re(s)',
				validate: function(field, validatorOptions){
					var fClass = this.getSelectorMotifFieldClass(field, validatorOptions.selectorMotif);
					var minLength = fClass.replace( new RegExp(validatorOptions.selectorMotif), '$1' );
					return $(field).val().length >= minLength;
				}
			},
			max_length: {
				selectorMotif: /validator_max_length_(\d+)/,
				errorMessage: 'Ce champ doit comporter au maximum $1 caract&egrave;re(s)',
				validate: function(field, validatorOptions){
					var fClass = this.getSelectorMotifFieldClass(field, validatorOptions.selectorMotif);
					var maxLength = fClass.replace( new RegExp(validatorOptions.selectorMotif), '$1' );
					return $(field).val().length <= maxLength;
				}
			},
			length: {
				selectorMotif: /validator_length_(\d+)/,
				errorMessage: 'Ce champ doit avoir $1 caract&egrave;res',
				validate: function(field, validatorOptions){
					var fClass = this.getSelectorMotifFieldClass(field, validatorOptions.selectorMotif);
					var length = fClass.replace( new RegExp(validatorOptions.selectorMotif), '$1' );
					return $(field).val().length == length;
				}
			},
			type_date_fr: {
				selector: '.validator_type_date_fr',
				errorMessage: 'Date incorrecte',
				validate: function(field, validatorOptions){
					var motif = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
					if( ! field.value.match(motif) ){
						return false;
					}

					var parts = field.value.split('/');

					if( parts[0] >= 1 && parts[0] <= 31 && parts[1] >= 1 && parts[1] <= 12 ){
						return true;
					}else{
						return false;
					}
				}
			},
			type_email: {
				selector: '.validator_type_email',
				errorMessage: 'Email invalide',
				validateWithRegExp: /^[\w\-]+(\.[\w\-]+)*@[\w\-]+(\.[\w\-]+)*\.[\w\-]{2,4}$/
			},
			type_html_color: {
				selector: '.validator_type_html_color',
				errorMessage: 'Ce champ doit &ecirc;tre une couleur HTML valide (Exemple: #A1B2C3)',
				validateWithRegExp: /^#[0-9A-F]{6}$/i
			},
			type_integer: {
				selector: '.validator_type_integer',
				errorMessage: 'Ce champ doit &ecirc;tre un nombre entier',
				validateWithRegExp: /^\d+$/i
			},
			type_numeric: {
				selector: '.validator_type_numeric',
				errorMessage: 'Ce champ doit &ecirc;tre un nombre d&eacute;cimal',
				validate: function(field){
					var value = $(field).val();
					return parseFloat(value) == value;
				}
			},
			type_phone_number_fr: {
				selector: '.validator_type_phone_number_fr',
				errorMessage: 'Num&eacute;ro t&eacute;l. : s&eacute;rie de 10 chiffres',
				validateWithRegExp: /^\d{10}$/i
			},
			type_zip_code: {
				selector: '.validator_type_zip_code',
				errorMessage: 'Code postal invalide',
				validateWithRegExp: /^\d{5}$/i
			},
			text_only: {
				selector: '.validator_text_only',
				errorMessage: 'Texte uniquement',
				validateWithRegExp: /^[a-z ���������������������������-]+$/i
			}
		},

		options: {
			validateOn: [ 'click', 'blur' , 'change', 'keyup'] //, 'focus' ]
		},

		addValidator: function(validatorName, config){
			this.validators[ validatorName ] = config;
		},

		checkValidator: function(field, validatorName){
			var validator = this.validators[ validatorName ];

			if( $.isFunction( validator.validate ) ){
				return validator.validate.apply( this, [field, validator] );
			}else if( validator.validateWithRegExp ){
				return $(field).val().match( new RegExp(validator.validateWithRegExp) ) !== null;
			}else{
				alert('V&eacute;rification du validateur ' + validatorName + ' impossible');
				return false;
			}
		},

		getErrorMessage: function(field, validatorName){
			var errorMessage = this.validators[ validatorName ]['errorMessage'];

			if( this.validators[ validatorName ]['selectorMotif'] ){
				var fClass = this.getSelectorMotifFieldClass( field, this.validators[ validatorName ]['selectorMotif'] );
				return fClass.replace( this.validators[ validatorName ]['selectorMotif'], errorMessage );
			}else{
				return errorMessage;
			}
		},

		getSelectorMotifFieldClass: function(field, selectorMotif){
			var fieldClassList = $(field).attr('class').split(' ');

			for(var i = 0; i < fieldClassList.length; ++i){

				if( fieldClassList[i].match( selectorMotif ) !== null ){
					return fieldClassList[i];
				}
			}

			return null;
		},

		hasValidator: function( field, validatorName ){
			var selectorMotif = this.validators[ validatorName ].selectorMotif;

			if( typeof selectorMotif != "undefined" ){
				return this.getSelectorMotifFieldClass( field, selectorMotif );
			}else{
				return $(field).is( this.validators[ validatorName ].selector );
			}
		},

		init: function(){
			for( var i = 0; i < this.options.validateOn.length; ++i ){
				// tous les champs ayant un validateur sont v�rifi�s
				$(':input[class*="validator_"]').live( this.options.validateOn[i], function(){
					FieldValidator.validateField( this );
				});
			}
		},

		validateField: function( field, forceErrorDisplay ){
			var jField = $(field);

			var errors = [], isValid = true;

			// si le champ n'est pas obligatoire et qu'il est vide
			if( ! this.hasValidator(field, 'required') && ! this.checkValidator(field, 'required') && $.inArray( $(field).attr('type'), ['checkbox', 'radio'] ) == -1 ){
				// on peut ignorer les autres validateurs
				jField.removeClass('fieldInvalid');
				jField.trigger('validator:fieldIsValid');
				return;
			}

			for(var validatorName in this.validators){
				// si le champ est soumis � ce validateur et qu'il ne le respecte pas
				if( this.hasValidator(field, validatorName) && ! this.checkValidator(field, validatorName) ){
					isValid = false;

					var errorMsg = this.getErrorMessage( field, validatorName );

					if( errorMsg != '' ){
						// si la propri�t� 'required' n'est pas v�rifi�e, le message d'erreur 'required' est affich� sans se pr�occuper des autres validateurs
						if( validatorName == 'required' ){
							errors = [ this.getErrorMessage( field, validatorName ) ];
							break;
						}else{
							errors.push( this.getErrorMessage( field, validatorName ) );
						}
					}
				}
			}

			if( ! isValid ){
				jField.addClass('fieldInvalid');

				if( errors.length > 0 ){
					jField.data('validator_error_message', errors.join('<br />'));
					jField.data('validator_force_display_error', errors.join('<br />'));
					jField.trigger('validator:fieldIsInvalid');
				}else{
					jField.removeData('validator_error_message');
				}
			}else{
				jField.removeClass('fieldInvalid');
				jField.removeData('validator_error_message');
				jField.removeData('validator_force_display_error');
				jField.trigger('validator:fieldIsValid');
			}

			return isValid;
		}
	}

	FormValidator = {
		init: function( formId ){
			var form = $( '#' + formId );

			form.submit(function(){
				var formFields = document.getElementById(formId).elements, nbFields = formFields.length, formIsValid = true, isAjax = false, errors = [];

				for(var i = 0; i < nbFields; ++i )
				{
					// if( $(formFields[i]).attr('disabled') === false )// le disabled semble d�conner
					if( ! $(formFields[i]).is(':input:not(:visible):not([type="hidden"])') ) // on exclut les champs non visibles qui ne sont pas des <input type="hidden" ... />
					{
						if( FieldValidator.validateField( formFields[i], true ) === false ){
							errors[ formFields[i] ] = $( formFields[i] ).data('validator_error_message');
							formIsValid = false;
						}
					}
				}

				if( ! formIsValid ){
					alert('Vous devez remplir tous les champs correctement');
					// TODO trouver le script qui ajoute ce style
					// $('input.fieldInvalid').css('background-color','rgb(255, 203, 203)');
				}

				// Message d'erreur
				var container = $('#frm_error_msg');
				if(container.size() != 0) {
					var errMsg = '';
					$('.fieldInvalid').each(function() {
						if($.inArray($(this).attr('type'),['checkbox', 'radio']) != -1)
							return;
						var lbl = $('label[for='+$(this).attr('id')+']').text();
						if(lbl.length == 0)
							lbl = $('#field_'+$(this).attr('id')).text();
						lbl.replace(':','').replace(/(?:^\s+|\s+$)/g, "");
						if(lbl.length > 0)
							if(errMsg.length == 0)
								errMsg += ' "'+lbl+'"';
							else
								errMsg += ', "'+lbl+'"';
					});
					if(errMsg.length > 0)
					{
						container.text('Veuillez remplir correctement les champs suivants :'+errMsg+'.');
					}
				}

				return formIsValid;
			});
		}
	};
})(jQuery);

jQuery(function($){
	
	var debug = jQuery(':input.validator_required');
	
	// quand on focus un champ requis
	jQuery(':input.validator_required').live('focus', function(){
		// le message d'erreur n'est affich� qu'au blur lorsque le champ est vide au moment du focus et que ce n'est pas un bouton radio ou une case � cocher
		$(this).data( 'displayOnlyOnBlur', $.trim( $(this).val() ) == '' && $.inArray( $(this).attr('type'), ['checkbox', 'radio'] ) == -1 );
	});
	
	// quand on quitte un champ invalide
	$(':input.fieldInvalid').live('blur', function(){
		if( $(this).data('validator_error_message') != null ){
			// on affiche le message d'erreur
			$('#id_check_img_' + this.id)
				.html( '<img src="/images/form-no.jpg" alt="Erreur"/><span style="color: #CC0000">' + $(this).data( 'validator_error_message' ) + '</span>' );
		}
	});

	$(':input[class*="validator_"]')
		// quand on re�oit une notification que le champ est valide
		.live('validator:fieldIsValid', function(){
			var spanId;

			switch( $(this).attr('type').toLowerCase() ){
				case 'checkbox':
				case 'radio':
					spanId = 'id_check_img_' + $(this).attr('name').replace('[]', '');
					break;
				default:
					spanId = 'id_check_img_' + this.id;
			}

			var imgSpan  = $( '#' + spanId );
			// TODO : Temporaire pour compa market et media, � remplacer !
			if(imgSpan.size() == 0) imgSpan = $('#id_check_img_centres_interet');
			imgSpan.html( '<img src="/images/form-yes.jpg" alt="Valide"/>' );
		})
		// quand on re�oit une notification que le champ est invalide
		.live('validator:fieldIsInvalid', function(){
			// s'il n'y a aucun message d'erreur � afficher
			if( $(this).data('validator_error_message') == null || $(this).data('validator_error_message') == '' ){
				// on ignore la suite
				return;
			}

			if( typeof $(this).data('displayOnlyOnBlur') == 'undefined' ){
				// le message d'erreur n'est affich� qu'au blur lorsque le champ est vide au moment du focus et que ce n'est pas un bouton radio ou une case � cocher
				$(this).data( 'displayOnlyOnBlur', $.trim( $(this).val() ) == '' && $.inArray( $(this).attr('type'), ['checkbox', 'radio'] ) == -1 );
			}

			if( $(this).data('dontDisplayError') === true ){
				$(this).removeData('dontDisplayError');
			}
			// si on peut afficher le champ imm�diatement (sauf attendre que le champ perde le focus)
			else if( $(this).data('validator_force_display_error') || ! $(this).data('displayOnlyOnBlur') ){
				var spanId;

				switch( $(this).attr('type').toLowerCase() ){
					case 'checkbox':
					case 'radio':
						spanId = 'id_check_img_' + $(this).attr('name').replace('[]', '');
						break;
					default:
						spanId = 'id_check_img_' + this.id;
				}
				var imgSpan  = $( '#' + spanId );
				// TODO : Temporaire pour compa market et media, � remplacer !
				if(imgSpan.size() == 0) imgSpan = $('#id_check_img_centres_interet');
				imgSpan.html( '<img src="/images/form-no.jpg" alt="Erreur"/><span style="color: #CC0000">' + $(this).data( 'validator_error_message' ) + '</span>' );
			}
		});

	FieldValidator.init();
});
