/* CREDITS
 * ----------------------------------------------------------
 * Title:		Inventis - Mootools Form Validator
 * Author:		Dieter Verjans <dieter@inventis.be>
 * Date:		13/10/2009
 * ----------------------------------------------------------
 * Inventis - Web Architects - We design the Web!
 * www.inventis.be
*/


var Validator = new Class({
	Implements: [Options, Events],
	initialize: function(form, fields, showErrorsBottom, showErrorTextOnNewLine) {
		if(!$(form)) return false;
		this.form = $(form);
		
		this.fields = fields;		
		this.showErrorTextOnNewLine = (showErrorTextOnNewLine?true:false);
		this.showErrorsBottom = (showErrorsBottom == false ?false:true);		
		this.valid = true;
		this.invalidFields = new Array();			
		this.assignFieldEvents();		
		
		$(this.form).addEvent('submit', function(e){
			new Event(e).stop();
			return this.onSubmit(e);
		}.bind(this))
	},
	
	assignFieldEvents: function(){
		$each(this.fields, function(validator, name){
			if(!validator || !name) return false;
			var field = this.fetchField(name);
			if(field){
				var validatorsArr = this.splitValidators(validator);
				this.checkIfRequired(field, validatorsArr)
				field.addEvent('blur', function(){
					this.validateField(field, validatorsArr);
				}.bind(this))
			}
		}.bind(this));
	},
	
	fetchField : function(name){
		var field = false;
		
		//fetch by id
		field = $(name);		
		if(field != null) return field;
				
		//not found by id, try to fetch input by name
		field = this.form.getElement('input[name='+name+']');			
		if(field != null) return field;
		
		//not found by id, try to fetch textarea by name
		field = this.form.getElement('textarea[name='+name+']');					
		if(field != null) return field;
		
		return false;
	},
	
	checkIfRequired : function(field, validatorsArr){
		var infoField = this.getInfoField(field);
		if (infoField) {
			validatorsArr.each(function(validator, index){
				var validatorData = validator.split(':');
				var validatorName = validatorData.shift();
				
				if (validatorName == 'required') {
					infoField.addClass('required');
				}
				
			}.bind(this));
		}
		
	},
	
	getInfoField : function(field){
		var infoField = field.getNext();
		if(infoField.tagName == 'SPAN')
			return infoField;
		else
			return false;
	},
	
	splitValidators : function(validator){
		if(validator)
			return validator.split("|");
		else
			return [];
	},	
	
	validateField : function(field, validatorsArr){
		field.isValid = true;
		field.isRequired = false;
		var totalValidators = validatorsArr.length;
		var last = false;
		validatorsArr.each(function(validator, index){
			if (field.isValid) {
				if(index == (totalValidators-1)) last= true;
							
				var validatorData = validator.split(':');
				var validatorName = validatorData.shift();
				var validatorArguments = validatorData;
				
				var code = 'var fnc = ValidatorRules.' + validatorName;
				eval(code);
				
				if(validatorName == 'required')
					field.isRequired = true;
				
				var parameters = field.get('value');
				if(validatorArguments[0]) parameters += ':' + validatorArguments[0];
				if(validatorArguments[1]) parameters += ':' + validatorArguments[1];						
				
				var result = fnc.run(parameters);
				if (result != true) {
					field.isValid = false;
					this.invalidFields.push(field);
					this.valid = false;
					this.setError(field, result)
				}
				else {
					if(field.isRequired || field.get('value').length > 0)
						this.setCorrect(field, last);
					else
						this.setEmpty(field);
				}
			}
			
		}.bind(this))
	},
	
	setError: function(field, msg){
		var infoField = this.getInfoField(field);
		if (infoField) {
			infoField.removeClass('correct');
			infoField.removeClass('required');
			infoField.addClass('error');
			infoField.title = msg;
			if(this.showErrorTextOnNewLine) msg = "&nbsp;<br />" + msg;			
			if(this.form.id != 'promoCodeForm')
			{
				infoField.innerHTML = msg;
				field.errorMsg = msg;
			}
			field.addClass('error');
		}
	},
	
	setCorrect: function(field, last){
		var infoField = this.getInfoField(field);
		if (infoField) {
			infoField.removeClass('error');
			infoField.removeClass('required');			
			infoField.addClass('correct');
			infoField.innerHTML = '&nbsp;';
			field.errorMsg = false;
			field.removeClass('error');
			if(last && $("fld_error_" + field.name))$("fld_error_" + field.name).destroy();
		}
	},
	
	setEmpty: function(field){
		var infoField = this.getInfoField(field);
		if (infoField) {
			infoField.removeClass('error');
			infoField.removeClass('required');
			infoField.removeClass('correct');
			infoField.innerHTML = '&nbsp;';
			field.errorMsg = false;
			field.removeClass('error');
		}
	},
	
	onSubmit: function(){
		this.valid = true;
		this.invalidFields = new Array();	
		if($('formErrors'))
			$('formErrors').destroy();
			
		$each(this.fields, function(validator, name){
			var field = this.fetchField(name);
			if(field){
				this.validateField(field, this.splitValidators(validator));				
			}			
		}.bind(this));
		
		if (!this.valid) {
			if(this.showErrorsBottom)
				this.showErrors();
				
			return false;			
		}
			
		this.form.submit();
	},
	
	showErrors: function(){
		var div = new Element('div', {id : 'formErrors'})
		var ul = new Element('ul');
	
		$each(this.invalidFields, function(field, index){
			var labelText = field.getPrevious().get('text').replace('*', '');
			labelText = labelText.replace(':', '');
			labelText = labelText.replace(/\s*$/, '');
			var li = new Element('li', {'id' : 'fld_error_' + field.name});			
			var link = new Element('a', {
				text: labelText,
				styles : {
					'cursor' : 'pointer'
				},
				events: {
					'click': function(){
						if(field.tagName != "SELECT")						
							field.select();
							
						field.focus();
						var label = field.getPrevious();
						var y= label.getPosition().y;						
						window.scrollTo(window.getScrollLeft(), y - (label.getHeight()/4));
					}
				}
			})
			link.injectBottom(li);
			var span = new Element('span', {text: ': ' + field.errorMsg.replace("FIELD"	, '')});
			span.injectBottom(li);
			li.injectBottom(ul);			
		}.bind(this));
		
		ul.injectBottom(div);
		var placeTo = this.form.getElement('button');
		if(this.form.getElement('button').getParent())placeTo = this.form.getElement('button').getParent();
		div.injectBefore(placeTo);
	}
})

var ValidatorRules = {
	
	min : function(params){
		var paramsData = params.split(':');
		var string = paramsData.shift();
		var args = paramsData;
		var size = args[0];
		
		if (trim(string) != '' && string.length < size){
			var error = "Veld moet minimaal %1$s karakters bevatten"
			return error.replace('%1$s', size);
		}
			
		return true;
	},
	
	max : function(params){
		var paramsData = params.split(':');
		var string = paramsData.shift();
		var args = paramsData;
		var size = args[0];
		
		if (trim(string) != '' && string.length > size){
			var error = "Veld mag maximaal %1$s karakters bevatten"
			return error.replace('%1$s', size);			
		}
			
		return true;
	},
	
	exact : function(params){
		var paramsData = params.split(':');
		var string = paramsData.shift();
		var args = paramsData;
		var size = args[0];
		
		if (trim(string) != '' && string.length != size){
			var error = "Veld moet exact %1$s karakters lang zijn"
			return error.replace('%1$s', size);			
		}
			
		return true;
	},
	
	required : function(string){
		if(trim(string) == '')
			return "Veld is verplicht in te vullen";
		return true;
	},
	
	date : function(string){ // format: dd-mm-yyyy
		if(trim(string) != '')
		{
			var array = string.split('-');
			if(array.length == 1) array = string.split('-');
			if(array.length == 1) array = string.split(' ');
			
			if(checkDate(array[0], array[1], array[2]))
				return true;
			else			
				return "Dit is geen geldige datum, formaat: DD-MM-YYYY (voorbeeld: 30-05-2007)";
		}
		else
			return true;
	},
	
	email : function(string){
		if(trim(string) == '')
		 return true;		
		
		var result = string.test(/^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i);
		if(result)
			return true;
		else
			return "Ongeldig e-mailadres";
	},
	
	telephone : function(string){
		if(trim(string) != '')
		{
			//belgian number 9 or 10 digits
			var number = string.replace(/\//g, '');
			number = number.replace(/\./g, '');
			
			if(number.length < 9 || number.length > 10)
				return "Dit is geen geldig telefoonnummer";
			else			
				return true;
		}
		else
			return true;
	},
	
	financial : function(string){
		if(trim(string) != '')
		{
			//belgian number
			var bankaccount = string.replace(/\-/g, '');
			bankaccount = bankaccount.replace(/\./g, '');
			
			var firstPart = bankaccount.substr(0, 10);
			var value = (firstPart%97);
			
			if(bankaccount.length != 12 || value != bankaccount.substr(-2,2))
				return "Ongeldig bankrekeningnummer";
			else			
				return true;
		}
		else
			return true;
	},
	
	vat : function(string){
		if(trim(string) != '')
		{
			//belgian
			var landcode = trim(string.substr(0,3));
			var number = 0;
			if(landcode.toUpperCase() == 'BE')
				number = string.substr(3);
			else
				number = string;
			
			number = number.replace(/\./g, '');
			
			if(number.length == 9)
				return true;
			else if(number.length == 10 && number.substr(0,1) < 2)
				return true;
			else		 
				return "Ongeldig btwnummer";
		}
		else
			return true;
	},
	
	url : function(string){
		if(trim(string) == '')
		 return true;		
		
		var result = string.test(/[a-z0-9.-]+\.[a-z]{2,6}$/i);
		if(result)
			return true;
		else
			return "Ongeldige url";
	},
	
	mysqltimestamp : function(string){
		if(trim(string) == '')
			return true;		
		
		var result = string.test(/[0-9]{1}[0-9]{1}[0-9]{1}[0-9]{1}-[0-1]{1}[0-9]{1}-[0-3]{1}[0-9]{1} [0-2]{1}[0-9]{1}:[0-6]{1}[0-9]{1}:[0-6]{1}[0-9]{1}/i);
		if(result)
			return true;
		else
			return "Dit is geen geldige datum. Formaat: YYYY-MM-DD HH:MM:SS";
	},
	
	match: function(params){
		var paramsData = params.split(':');
		var string = paramsData.shift();
		var args = paramsData;			
		var field = false;
		
		//fetch by id
		field = $(args[0]);		
		if(field == null || field == "null") field = false;
				
		//not found by id, try to fetch input by name
		if (!field) {
			field = $(document.body).getElement('input[name='+args[0]+']');			
			if(field == null || field == "null") field = false;
		}
		
		//not found by id, try to fetch textarea by name
		if (!field) {
			field = $(document.body).getElement('textarea[name=' + args[0] + ']');
			if(field == null || field == "null")
				field = false;
		}
					
		var confirmValue = field.value;
		
		if(trim(string) != '' || trim(confirmValue) != ""){
			if(string == confirmValue)
				return true;
			else
				return "Velden zijn niet gelijk.";
		}
		else
		 	return true;
	},
	
	matchstring: function(params){
		var paramsData = params.split(':');
		var string = paramsData.shift();
		var args = paramsData;
		var confirmValue = args[0];
		
		if(trim(string) == '')
			return true;
		else if (string == confirmValue)
			return true;
		else
			return "Deze code komt niet overeen met de code op de afbeelding, probeer opnieuw.";
	},
	
	alphabetic: function(string){
		if(trim(string) == '')
			return true;		
		
		var result = string.test(/^([-a-z])+$/i);
		if(result)
			return true;
		else
			return "Niet alfabetisch";
	},
	
	alphanumeric: function(string){
		if(trim(string) == '')
			return true;		
		
		var result = string.test(/^([-a-z0-9])+$/i);
		if(result)
			return true;
		else
			return "Niet alfanumeriek";
	},
	
	numeric: function(string){
		if(trim(string) == '')
			return true;		
		
		var result = string.test(/^[0-9\.]+$/);
		if(result)
			return true;
		else
			return "Niet numeriek";
	},
	
	range: function(string){
		var paramsData = params.split(':');
		var string = paramsData.shift();
		var args = paramsData;		
		
		if (trim(string) != '' && (string < args[0] || string > args[1]))
			return "Deze moet tussen %1$s en %2$s liggen.";
		else
			return true;
	}
}


function trim(value) {
  value = value.replace(/^\s+/,'');
  value = value.replace(/\s+$/,'');
  return value;
}

function checkDate (day,month,year) {
// checks if date passed is valid
// will accept dates in following format:
// isDate(dd,mm,ccyy), or
// isDate(dd,mm) - which defaults to the current year, or
// isDate(dd) - which defaults to the current month and year.
// Note, if passed the month must be between 1 and 12, and the
// year in ccyy format.

	if(day.length != 2) return false;
	if(month.length != 2) return false;
	if(year.length != 4) return false;

    var today = new Date();
    year = ((!year) ? y2k(today.getYear()):year);
    month = ((!month) ? today.getMonth():month-1);
    if (!day) return false
    var test = new Date(year,month,day);
    if ( (y2k(test.getYear()) == year) &&
         (month == test.getMonth()) &&
         (day == test.getDate()) )
        return true;
    else
        return false
}

function y2k(number) { return (number < 1000) ? number + 1900 : number; }
