/**
 * @constructor FormValidator
 * @classDescription validate form fields
 * @author Erick Olivera
 * @copyright Trio Solutions
 */

function FormValidator (formNode){
	this.errorMessage = "";
	this.formNode = formNode;
}

FormValidator.prototype = {
	addRule:function(fieldName, message, validatorType, args){
		validatorType = validatorType.toLowerCase(validatorType);
		var element = this.formNode[fieldName];
		if(element != null){
			switch(validatorType){
				case "different":
				  this.different(element, message, args);
				break;
				case "required":
					this.required(element, message);
				break;
				case "rangelength":
					this.rangelength(element, message, args[0], args[1]);
				break;
				case "rangevalues":
					this.rangevalues(element, message, args[0], args[1]);
				break;
				case "numeric":
					this.numeric(element, message);				
				break;
				case "positivenumber":
					this.positivenumber(element, message);				
				break;
				case "integer":
					this.integer(element, message);
				break;
				case "positiveinteger":
					this.positiveinteger(element, message);
				break;
				case "lettersonly":
					this.lettersonly(element, message);				
				break;
				case "zipcode":
					this.zipcode(element, message);				
				break;
				case "email":
					this.email(element, message);
				break;
				case "ischecked":
					this.ischecked(element, message, args);
				break;
				case "compare":
				  var elementPivot = this.formNode[(typeof args == 'object' && args.length)? args[0] : args];
				  if(elementPivot != null){
				  	if(typeof args == 'object' && args.length){
						this.compare(element, message, elementPivot, args[1]);	
					}else{
						this.compare(element, message, elementPivot);
					}
				  }
						
				  
				  
				break;
				case "creditcard":
					this.creditcard(element, message);
				break;
				case "expression":
					this.expression(element, message, args);
				break;
				default:
				//
			}
		}		
	},
	
	markField:function(element, bg_color, border_color){
		if(element.length){
			for(var j=0; j<element.length; j++){
				element[j].style.backgroundColor = bg_color; 
				element[j].style.borderColor = border_color;
			}	 		
		}else{
			element.style.backgroundColor = bg_color; 
			element.style.borderColor = border_color;
		}	
		 
	},
	getValue:function(e){
		var r = '';
		if(e.tagName == 'SELECT'){
			if(e.selectedIndex != -1){
				r = e.options[e.selectedIndex].getAttribute('value');
				if(!r){
					r = e.options[e.selectedIndex].text;
				}
			}else{
				r = '';
			}
		}else if(e.length != undefined){
			for(i = 0; i < e.length; i++){
				if(e[i].checked){
					r = e[i].value;break;
				}
			}
		}else{
			r = e.value;
		}
		return r;
	},
	
	invalidField:function(element, message){
		this.markField(element, "#F5EDB4", "#FF9933");
		this.errorMessage =this.errorMessage + message+"\n";
	},
	
	required:function(element, message){
		if(!/\S/.test(this.getValue(element))){
			this.invalidField(element, message);
		}
	},
	
	rangelength:function(element, message, minLength, maxLength){
		var val = this.getValue(element);
		if((minLength!=null && val.length < minLength) || (maxLength!=null && val.length > maxLength) ){
			this.invalidField(element, message);	
		}
	},
	
	rangevalues:function(element, message, minValue, maxValue){
		var val = this.getValue(element);
		if((minValue!=null && val < minValue) || (maxValue!=null && val > maxValue) ){
			this.invalidField(element, message);	
		}
	},
	
	numeric:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^(\-?(\d+\.?\d+)|(-?\d+)){1}$/.test(val)){
			this.invalidField(element, message);	
		}
	},
	
	positivenumber:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^((\d+\.?\d+)|(\d+)){1}$/.test(val)){
			this.invalidField(element, message);	
		}
	},
	
	integer:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^-?\d+$/.test(val)){
			this.invalidField(element, message);	
		}
	},
	
	positiveinteger:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^\d+$/.test(val)){
			this.invalidField(element, message);	
		}
	},
	
	lettersonly:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^[a-zA-Z\s]+$/.test(val)){
			this.invalidField(element, message);	
		}
	},
	
	zipcode:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^\d{5}$/.test(val)){
			this.invalidField(element, message);	
		}
	},
	
	email:function(element, message){
		var val = this.getValue(element);
		if(val.length > 0 && !/^\S+@\S+(\.\S+)*\.(\S{2,3}|info)$/i.test(val) || /[\(\)\<\>\,\;\:\\\"\[\]]/.test(val))
		{
			this.invalidField(element, message);
		}
	},
	ischecked:function(element, message, args){
		var me = this;
		var operator = "or";
		function verifyGroup(element){
			var i=0;
			var flag=(operator == 'and') ? true : false;
			if(element.length){
				while (i < element.length){
					if(operator == "and"){
						flag = flag && element[i].checked; 
					}else{
						flag = flag || element[i].checked; 
					}
					i++;	
				}
				if(!flag){
					for(var j=0; j<element.length; j++)
					  me.markField(element[j],"#F5EDB4", "#FF9933");
					me.invalidField(element[0], message);
				}	 		
			}else{
				if(element.checked == false)
					me.invalidField(element, message);
			}	
		};
		if(args){
			operator = (args[0].toLowerCase()== "all") ? "and" : "or";
			if(args.length > 1){
				var tmpArr = new Array();
				tmpArr = tmpArr.concat(element);
				for(var i=1; i < args.length; i++){
					tmpArr = tmpArr.concat(me.formNode[args[i]]);
				}
				element = tmpArr;
			} 
		}
		verifyGroup(element);		
	},
	
	compare:function(element, message, elementPivot, relation){
		var val  = this.getValue(element),
		    valPivot = this.getValue(elementPivot),
		    error = false;
		
		if(!relation){
			relation = '==';	
		}
		
		switch(relation){
		  case '<':
		    error = !(val < valPivot);    
		  break;
		  case '<=':
		    error = !(val <= valPivot);
		  break;
		  case '>':
		    error = !(val > valPivot);
		  break;
		  case '>=':
		    error = !(val >= valPivot);
		  break;
		  case '==':
		    error = !(val == valPivot);
		  break;
		  case '!=':
		    error = !(val != valPivot);
		  break;
		}
		if(error){
			this.markField(elementPivot, "#F5EDB4", "#FF9933");
			this.invalidField(element, message);
		}
	},
	
	expression:function(element, message, regularExpression){
		if(!regularExpression.test(this.getValue(element))){
			this.invalidField(element, message);
		}
	},
	
	different:function (element, message, reference){
	  var s = this.getValue(element);
	  if( s.toLowerCase() == reference.toLowerCase()){this.invalidField(element, message); return;}
	},
	
	creditcard:function(element, message, regularExpression){
		var v = "0123456789",
				w = "",
				s = this.getValue(element);
		
		s = s.replace(/\D/g, "");
		
		for (i=0; i < s.length; i++) {
			x = s.charAt(i);
			if (v.indexOf(x,0) != -1)
				w += x;
		}
		j = w.length / 2;
		if (j < 6.5 || j > 8 || j == 7) {this.invalidField(element, message); return;}
		k = Math.floor(j);
		m = Math.ceil(j) - k;
		c = 0;
		
		for (i=0; i<k; i++) {
			a = w.charAt(i*2+m) * 2;
			c += a > 9 ? Math.floor(a/10 + a%10) : a;
		}
		
		for (i=0; i<k+m; i++){ c += w.charAt(i*2+1-m) * 1};
		if(c%10 != 0){
			this.invalidField(element, message);
		}
	},
	
	validate:function(){
		if(this.errorMessage != ""){
			alert(this.errorMessage);
			return false;
		}	
		return true;	
	}
};
