/**
 *
 * Pork formValidation class:
 * Usage:
 *
 * 
 * 
 *  <script>
 *  formValidations = { // if you have just one form onscreen, just define the validations array as formValidations.
 * 
 *				'Adres_Email': { mandatory: true,	validation: 'email'	}, // key can be name or ID 
 *				'Adres_Adres': { mandatory: true, validation: 'anything'	},
 *				'Adres_Huisnummer': {mandatory: true, validation: 'alfanum'	},
 *				'Adres_Postcode': {mandatory: true, validation: 'zipcode' 	},
 *				'Adres_Woonplaats': {mandatory: true, validation: 'anything'}, 
 *        '.cssClass' : { mandatory : true },
 *        '.newhoeveelheid' : { validation: 'number', dependsOn: function(el) { return el.getParent().getNext().getFirst() } }, // dependsOn expects a handle to an element that is also to be validated.
 *        '.newdate'  : { validation: 'date', dependsOn: function(el) { return el.getParent().getPrevious().getFirst() } }
 *        '.custom' : { validation: function(el) { return el.value == 'black' } }
 *	 }
 * 
 *  customValidations = {
 *		'naam' : { mandatory: true, validation: 'anything' },
 *		'adres' : { mandatory: true, validation: 'anything', message: 'Adres mag niet leeg zijn!', unvalidatedClass: 'test' }
 *  }
 *  </script>
 *
 *  <form method='post' id='woei' onsubmit="return $(this).validate();">
 *
 *  <form method='post' id='woei' onsubmit="return $(this).validate(customValidations);">
 */



FormValidator = new Class({
	Implements: Options,

	initialize: function(form, options)
	{
		this.form = form;
		this.setOptions(options, this.defaultOptions);
		this.validatables = Array();
		return this;
	},

	defaultOptions: {
		validateOnBlur: false,
		unvalidatedClass: 'unvalidated',
		message: 'Er zijn nog fouten in het formulier.<br>Corrigeer deze voor je verder kan.<br>&nbsp;<br>Hint: Je doet iets fout bij de rood gemarkeerde velden   <img src="./images/wink.gif" alt=";-)" class="smiley" height="15" width="15">'
	},

	getRules: function()
	{	
		this.rules = window.formValidations;
	},

	hasRule: function(element)
	{
		return(typeof(this.rules.fields[element]) != 'undefined');
	},

	getRule: function(element)
	{
		return(this.rules[element]);
	},
  
	gatherElements: function() // zoek alle elementen bij elkaar en als er nog geen validateObject aan geknoopt is fix dit dan.
	{
		if(this.validatables.length == 0)
		{
		  for(var i in this.rules) // i kan zijn: een element name, een element ID of een element CSS selector
		  { 
			var elm = this.form.elements[i] || ( $(i) || false );  // set elm a.d.h.v. element name of id, of false.
			if(elm && !elm.validator)
			{ // als er 1 element is deze validaten.
			  elm.validator = new ValidateObject(this.rules[i], elm, this);
			  this.validatables[this.validatables.length] = elm;
			}
			else if( elements = $$(i) ) 
			{  // alleen als er elements zijn deze loopen 
			  for(j=0; j<elements.length; j++) 
			  {
				  if(!elements[j].validator) elements[j].validator = new ValidateObject(this.rules[i], elements[j], this);
				  this.validatables[this.validatables.length] = elements[j];
			  }
			}
		  }
		}
	},
	
	validate: function(rules)
	{
		this.rules = rules || this.getRules();
		var returnValue = true;
		this.gatherElements();
		for(i=0; i<this.validatables.length; i++)
		{
		  var val = this.validatables[i].validator.validate(false);
		  if(!val) returnValue = false;
		}
		if(!returnValue && this.options.message) this.showMessage();
		return returnValue;
	},
	
	showMessage: function()
	{
		 document.retrieve('roar').alert('Fout!', this.options.message);  
	},

	validateElement: function(element, rule)
	{
		element.validator = new ValidateObject(rule, element, this);
		return(element.validator.validate(true));
	}
});


ValidateObject = new Class({
	initialize: function(rule, element, validator)
	{
		this.element = $(element);
	    this.rule = rule;
		this.mandatory = this.rule.mandatory || false;
		this.validator = validator;
		this.validateFunc = false;
		this.unvalidatedClass = (this.rule.mandatory) ? this.validator.options.unvalidatedClass : (this.rule.unvalidatedClass || this.validator.options.unvalidatedClass);
		return this;
	},

	standardValidations: { // available regex validations.
				'email' : "^[0-9a-zA-Z._-]*[@][0-9a-zA-Z._-]*[.][a-z]{2,4}$", 
				'amount' : "^[-]?[0-9]+$",
				'number' : "^[-]?[0-9,]+$",
				'alfanum' : "^[0-9a-zA-Z ,.-_\\s\?\!]+$",
				'alphabet' : "^[a-zA-Z]+$",
				'anything' : "[a-z0-9A-Z ]+",
				'words' : "^[A-Za-z]+[A-Za-z \\s]*$",
				'phone' : "^[\+]{0,1}[0-9\-]{10,}$",
				'zipcode' : "^[1-9][0-9]{3}[ ]?[a-zA-Z]{2}$",
				'plate' : "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}$",
				'price' : "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?$",
				'2digitopt' : "^\d+(\,\d{2})?$",
				'2digitforce' : "^\d+\,\d\d$"
	},


	validate:function(independant)
	{

		if((!independant && !this.validateDependency()) || (this.mandatory && this.element.value.length == 0) ) return this.incorrect(); // only validate the dependant object if we have to.

		if(this.element.value.length > 0 && this.standardValidations[this.rule.validation])	{ // 
			return new RegExp(this.standardValidations[this.rule.validation]).test(this.element.value) ? this.correct() : this.incorrect();
		}    
		else if(this.element.value.length > 0)
		{
		  if(typeof this.rule.validation == 'function') { // if a custom validation function is passed along (validaton:function(el) 
			return this.rule.validation(this.element) ? this.correct() : this.incorrect();
		  } 
		  else {  // it could be just an extension of the formValidator element
			var func = ("validate-"+this.rule.validation).camelCase();
			if(func in this) return this[func]() ? this.correct() : this.incorrect();  
		  }
		}
		return this.correct();
	},
  
	validateDependency:function() // validate any depending objects.
	{
		if(this.rule.dependsOn) {
		  var dependency = this.rule.dependsOn(this.element); 
		  if(dependency && dependency.validator)
		  {
			this.mandatory = (dependency.value.length > 0) ? true : this.rule.mandatory; // if the other element is not empty, this one becomes mandatory.
			return (dependency.validator.validate(true)) ? this.correct() : this.incorrect();
		  }
		}
		return true;
	},
	
	incorrect: function()
	{
		if(!this.element.hasClass(this.unvalidatedClass)) {
			this.element.addClass(this.unvalidatedClass);	
			if(this.rule.message) alert(this.rule.message);
		}
		if($type(this.rule.onInCorrect) == 'function') { this.rule.onIncorrect(this.element) }
		return false;
	},

	correct: function()
	{
		if(this.element.hasClass(this.unvalidatedClass)) {
			this.element.removeClass(this.unvalidatedClass);
		}
		if($type(this.rule.onCorrect) == 'function') { this.rule.onCorrect(this.element) }
		return true;
	},
  
  validateDate: function(value)
  {
     if(new RegExp("^[0-9]{1,2}[-\/\.][0-9]{1,2}[-\/\.]([0-9]{1,2}|[0-9]{4})$").test(this.element.value))
     {
        date = this.element.value.split(/[-|/|\.]/);
        if(date[2].length == 2) date[2] = '20'+date[2];
        if(date[2].length == 1) date[2] = '200'+date[2];
        validDate = new Date(date[2], date[1] - 1, date[0], 1, 1, 0, 0);
      	this.element.value = validDate.getDate()+'-'+(validDate.getMonth() +1)+'-'+validDate.getFullYear();
        return true;
     }
     else
     {
        return false;
     }
  },

	validateBank:function(value)
	{
		value = this.element.value.split('.').join('').split(' ').join('').split('');
		var postbank  = "^[pP]{1}([0-9]{3,}$)";
		var bank = "^([0-9]{9}$)";
		var total = 0;
		if (new RegExp(bank).test(value.join(''))) {
			for (var i=1; i<10; i++) { total += value[i-1] * (10-i); }	
			if ((total % 11) == 0) return (true);
			else {
				alert('Bankrekeningnummer voldoet niet aan de 11-proef');
				return false;
			}
		}
		else if (new RegExp(postbank).test(value.join('')))	{ return (true); }
		else {
			alert('Niet genoeg cijfers voor een bankrekening! \nAls dit een postbankrekening betreft zet dan een "P" voor het getal, \nals dit een bankrekening nummer betreft zorg dan dat deze correct is.');
			return (false);
		}
	}
 
});

/*
Property: validate
	Validates a form using the FormValidator object

Arguments:
	options - option collection for the validator class

Returns:
	The boolean validated

Example:
	<script type='text/javascript'>

	oppervlakteValidations = {
		formattedBegintijd: { validation: 'date', mandatory: true},
		formattedBegintijd: { validation: 'date', mandatory: true},
		bruto: { validation: 'number', mandatory: true},
	}

	</script>
	<form id="myForm" action="submit.php" onsubmit="if( $(this).validate(oppervlakteValidations)) { $(this).send({update: 'editLocatie'}); } return false;"
	<input name="email" value="bob@bob.com">
	<input name="zipCode" value="90210">
	<input type='submit'>
	</form>
	(end)
*/
Element.implement({
	validate: function(validations, options){
		if(!this.validator) this.validator = new FormValidator(this);
		return this.validator.validate(validations, options);	
	},

	validateElement: function(validation, options) 
	{
		var validator = new FormValidator(this.form);
		return validator.validateElement(this, validation, options);					
	}
});


