var arrValidators=new Array();

//<<<<START of the constructor
function formValidator() {
	//Propriedades
	this.name=arguments[0]; //The name of the form
	this.errors=new Array(); //Array with all errors found
	this.rules=new Array(); //This array contains all the rules to apply
	this.fieldToFocus=null; //If an error is found, its field will be focused
	this.debugMode=(arguments[1]) ? arguments[1] : 0;
	//Methods
	this.handleFormValidatorError=function() { // Usar apenas para checar bugs no código (debug)
		if (this.debugMode==1) {
			alert("formValidator error: " + arguments[0]);
			return(false);
		}
		else return(false); //For debug mode 0 (standard), don't show error messages
	};
	this.handleError=function() {
		if (objField=='[object]')
			if (!this.fieldToFocus && objField.focus) this.fieldToFocus=arguments[0];
		this.errors[this.errors.length]=new error(arguments[0],arguments[1]);
	};
	this.initialize=function() {
		if (document.forms[this.name])
			document.forms[this.name].onsubmit=function() {
				return(eval("objVld_" + this.name + ".execute()"));
			}
		else
			return(this.handleFormValidatorError("The form '" + this.name + "' isn't present or it has not been loaded yet"));
	};
	this.addRule=function() { //Feeds rules array
		if (arguments[1]) {
			if (isArray(arguments[1]))
				arrRules=arguments[1];
			else
				arrRules=[arguments[1]];
		}
		else arrRules=["required"];
		for (intRule=0;intRule<arrRules.length;intRule++){
			this.rules[this.rules.length]=new rule(arguments[0],arrRules[intRule],(arguments[2]) ? arguments[2] : null,(arguments[3]) ? arguments[3] : null);
		}
	};
	this.execute=function() {
		objForm=document.forms[this.name];
		for (intRule=0;intRule<this.rules.length;intRule++) {
			objRule=this.rules[intRule];
			if (objForm[objRule.fieldName] || objRule.ruleType=="externalFunction") {
				objField=objForm[objRule.fieldName];
				switch (objRule.ruleType) {
					case "externalFunction": //Evaluates an external function
						extFunction=eval(objRule.fieldName);
							if (!extFunction) this.handleError(null,(objRule.errorMessage) ? objRule.errorMessage : "");
						break;
					case "date": // Exemplo correto: dd/mm/yyyy
						if (!isEmpty(getFieldValue(objField)) && !verifyDate(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser uma data válida");
						}
						break;
					case "cep": // Exemplo correto: 99999-999 / 99999999
						if (!isEmpty(getFieldValue(objField)) && !verifyCEP(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um CEP inválido");
						}
						break;
					case "email": //Exemplo correto a@b.c
						if (!isEmpty(getFieldValue(objField)) && !verifyMail(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um e-mail inválido");
						}
						break;
					case "tel": // Exemplo correto: 	(99)99999999 / (99)9999999 / (99)999999
						if (!isEmpty(getFieldValue(objField)) && !verifyTEL(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um telefone válido");
						}
						break;
					case "tel1": // Exemplo correto: 99 9999-9999 / 99 999-9999 / 99 99-9999
						if (!isEmpty(getFieldValue(objField)) && !verifyTEL1(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um telefone válido");
						}
						break;
					case "codigo": // Exemplo correto: 111111 / 111111
						if (!isEmpty(getFieldValue(objField)) && !verifyCodigo(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um codigo válido");
						}
						break;
					case "cgc": // Exemplo correto: 99.999.999/9999-99 / 99999999999999
						if (!isEmpty(getFieldValue(objField)) && !verifyCgc(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um CNPJ inválido");
						}
						break;
					case "cpf": // Exemplo correto: 999.999.999-99 / 99999999999
						if (!isEmpty(getFieldValue(objField)) && !verifyCpf(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um CPF inválido");
						}
						break;
					case "cpf/cgc": // Exemplo correto: 99.999.999/9999-99 / 99999999999999 or 999.999.999-99 / 99999999999
						if (!isEmpty(getFieldValue(objField)) && (!verifyCgc(getFieldValue(objField)) || !verifyCpf(getFieldValue(objField)))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um CNPJ ou CPF inválido");
						}
						break;
					case "integer": //o campo deve numérico
						if (!isEmpty(getFieldValue(objField)) && !verifyInteger(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um número inteiro válido");
						}
						break;
					case "link": // Se for um link invalido retorna erro
						if (!isEmpty(getFieldValue(objField)) && !verifyLink(getFieldValue(objField))) {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser um link inválido 'http://'");
						}
						break;
					case "required": // Checa se o campo está sem nenhum valor
						if (isEmpty(getFieldValue(objField))||getFieldValue(objField)=='(nn)xxnn-nnnn'||getFieldValue(objField)=='(dd/mm/aaaa)') {
							this.handleError(objField,(objRule.errorMessage) ? objRule.errorMessage : "O campo " + ((objRule.customFieldName) ? objRule.customFieldName : objField.name) + " deve ser preenchido");
						}
						break;
				}
			}
			//field not found
		}
		if (this.errors.length) { //Mostra os erros e para a execução do script
			strErrorMessage="Os seguintes erros foram encontrados no preenchimento do formulário:\n\n";
			arrUsedFields=new Array(); //A list of the fields with errors, used to avoid more than one message related to the same field
			for (intError=0;intError<this.errors.length;intError++) {
				if (!inArray(this.errors[intError].field,arrUsedFields)) {
					arrUsedFields[arrUsedFields.length]=this.errors[intError].field;
					strErrorMessage+="- " + this.errors[intError].message + "\n";
				}
			}
			alert(strErrorMessage);
			if (this.fieldToFocus) this.fieldToFocus.focus();
			this.errors=new Array(); //Limpando os valores...
			this.fieldToFocus=null; //Limpando os valores...
			return(false);
		}
		else return(true);
	};
	//Add the object to arrValidators Array
	arrValidators[arrValidators.length]=this;
}
//>>>>END of the constructor

function error(objField,strErrorMessage) { // Gera as mensagens de erro
	this.field=objField;
	this.message=strErrorMessage;
}

function rule(strFieldName,strRuleType,strCustomFieldName,strErrorMessage) { // Regras
	this.fieldName=strFieldName;
	this.ruleType=strRuleType;
	this.customFieldName=strCustomFieldName;
	this.errorMessage=strErrorMessage;
}

onload=function() {
	for (intValidator=0;intValidator<arrValidators.length;intValidator++) {
		arrValidators[intValidator].initialize();
	}
}

function getValidator(strFormName) {
	eval('objVld_' + strFormName + '=new formValidator(\'' + strFormName + '\');');
	return(eval('objVld_' + strFormName));
}

// Funções compartilhadas
function getFieldValue(objField) { // Pega os valores dos checkbox e radio
	strReturnValue='';
	if (objField[0]) {
		if (objField[0].type=="radio") {
			for (intRadio=0;intRadio<objField.length;intRadio++) {
				if (objField[intRadio].checked) strReturnValue=objField[intRadio].value;
			}
		}
		else if (objField.type=="select-one")
			strReturnValue=objField.options[objField.selectedIndex].value;
	}
	else
		strReturnValue=objField.value;
	return(strReturnValue);
}

function isArray(objAnyArray) { //returns a boolean indicating whether the argument is an array
	return((objAnyArray.sort) ? 1 : 0);
}

function inArray(value, arrAnyArray) { //returns a boolean indicating whether the first argument is present in the second, which must be an array
	for (intPos=0;intPos<arrAnyArray.length;intPos++)
		if (arrAnyArray[intPos]==value) return true;
	return(false);
}

function explode(arrAnyArray,strSeparator) {
	var strReturnValue="";
	for (intPos=0;intPos<arrAnyArray.length;intPos++)
		strReturnValue+=arrAnyArray[intPos] + strSeparator;
	strReturnValue=strReturnValue.substring(0,strReturnValue.length-strSeparator.length);
	return(strReturnValue);
}

function isEmpty(value) {
	if (isArray(value)) return(value.length==0);
	else return(value==null || trim(value)=="");
}

function trim(str) {
	var intChar,strChar,intStartIndex,intEndIndex;
	for (intChar=0;intChar<str.length;intChar++) {
		strChar=str.substr(intChar,1);
		if (strChar!=" " && strChar!="\n" && strChar!="\r" && strChar!="\t") {
			intStartIndex=intChar;
			break;
		}
	}
	for (intChar=str.length-1;intChar>=0;intChar--) {
		strChar=str.substr(intChar,1);
		if (strChar!=" " && strChar!="\n" && strChar!="\r" && strChar!="\t") {
			intEndIndex=intChar;
			break;
		}
	}
	return(str.substring(intStartIndex,intEndIndex+1));
}

function verifyCEP(strCEP) {
	return(!(strCEP.search("[0-9]{8}")==-1 && strCEP.search("[0-9]{5}-[0-9]{3}")==-1));
}

function verifyTEL(strTEL) {
	return(strTEL.search(/\([0-9]{2}\)[0-9]{6}$/)!=-1 || strTEL.search(/\([0-9]{2}\)[0-9]{7}$/)!=-1 || strTEL.search(/\([0-9]{2}\)[0-9]{8}$/)!=-1);
}

function verifyTEL1(strTEL) {
	return(strTEL.search(/[0-9]{2} [0-9]{2}-[0-9]{4}/)!=-1 || strTEL.search(/[0-9]{2} [0-9]{3}-[0-9]{4}/)!=-1 || strTEL.search(/[0-9]{2} [0-9]{4}-[0-9]{4}/)!=-1);
}

function verifyMail(strEmail) {
	strValidChars="@abcdefghijklmnopqrstuvxywzABCDEFGHIJKLMNOPQRSTUVXYWZ0123456789-_."; // Caracteres permitidos no campo email
	arrBoundaryChars=new Array();
	for (intPos=0;intPos<strEmail.length;intPos++) { // Checa se os caracteres são validos
		strThisChar=strEmail.substr(intPos,1);
		if (strValidChars.indexOf(strThisChar)==-1) {
			return(false);
		}
		if (strThisChar=="@" || strThisChar==".") {
			arrBoundaryChars[arrBoundaryChars.length]=parseInt(intPos);
		}		
	}
	for (intPos=0;intPos<arrBoundaryChars.length;intPos++) { // checa posicionamento dos pontos e underlines
		intThisItem=arrBoundaryChars[intPos]
		intNextItem=(intPos==arrBoundaryChars.length) ? 0 : arrBoundaryChars[intPos+1]
		if (intThisItem==0 || intThisItem==strEmail.length-1) {
			return(false);
		}
		if (intThisItem+1==intNextItem) {
			return(false);
		}
	}
		
	intFirstAtIndex=strEmail.indexOf("@");
	intLastAtIndex=strEmail.lastIndexOf("@");
	intFirstDotIndex=strEmail.indexOf(".");
	intLastDotIndex=strEmail.lastIndexOf(".");
	
	if (intFirstAtIndex!=intLastAtIndex || intFirstAtIndex==-1 || intFirstDotIndex==-1 || intLastDotIndex<intFirstDotIndex) {
		return(false);
	}
	return(true); // Se tudo estiver correto passa
}

function verifyDate(strDate) {
	strDate=trim(strDate);
	if(strDate!='(dd/mm/aaaa)'){
		if (strDate.search("[0-9]{2}\/[0-9]{2}\/[0-9]{4}")==-1) // Checa o campo data dd/mm/aaaa
			return(false);
		else {
			intDay=strDate.split("\/")[0];
			intMonth=strDate.split("\/")[1];
			intYear=strDate.split("\/")[2];
			if (intDay<1 || intMonth<1 || intMonth>12 || intYear<1900 || intYear>2100) return(false);
			arrLastMonthDay=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
			if (((intYear % 4 == 0) && intYear % 100 != 0) || intYear % 400 == 0) // Ano bissexto
				arrLastMonthDay[1]=29;
			if (intDay>arrLastMonthDay[intMonth-1]) return(false);
		}
	}
	return(true);
}

function verifyCgc(strCGC) {
	var intCGC='', intDig1=0, intDig2=0, intDigVerif1='543298765432', intDigVerif2='6543298765432';
	for (i=0;i<strCGC.length;i++) {
		if (strCGC.charAt(i) != " " && strCGC.charAt(i) != "." && strCGC.charAt(i) != "/" && strCGC.charAt(i) != "-" && strCGC.charAt(i) != "," && strCGC.charAt(i) != "\\") intCGC = intCGC + strCGC.charAt(i);
	}
	if (!isNaN(intCGC) && intCGC.length<=14) {
		return(verifyCNPJ_CPF(intCGC));
	} else 
		return(false);
}

function verifyCpf(strCPF) {
	var intCPF='', intDig1=0, intDig2=0; intInvers=11
	for (i=0;i<strCPF.length;i++) {
		if (strCPF.charAt(i) != " " && strCPF.charAt(i) != "." && strCPF.charAt(i) != "/" && strCPF.charAt(i) != "-" && strCPF.charAt(i) != "," && strCPF.charAt(i) != "\\") intCPF = intCPF + strCPF.charAt(i);
	}
	if (!isNaN(intCPF) && intCPF.length<=11 && intCPF!='') {
		return(verifyCNPJ_CPF(intCPF));
	} else 
		return(false);
}

function verifyCNPJ_CPF(pstrCNPJ_CPF) {
	var intCGC='', soma=0, ind=0, pos=0, resto=0, digito=0, dv='', x=0
	for (i=0;i<pstrCNPJ_CPF.length;i++) {
		if (pstrCNPJ_CPF.charAt(i) != " " && pstrCNPJ_CPF.charAt(i) != "." && pstrCNPJ_CPF.charAt(i) != "/" && pstrCNPJ_CPF.charAt(i) != "-" && pstrCNPJ_CPF.charAt(i) != "," && pstrCNPJ_CPF.charAt(i) != "\\") intCGC = intCGC + pstrCNPJ_CPF.charAt(i);
	}
	if (!isNaN(intCGC)){
		digito=intCGC.substr(intCGC.length-2)
		pstrCNPJ_CPF=intCGC.substr(0,intCGC.length-2)
		for (x=1;x<=2;x++) {
			soma=0
	        ind=2
			for (pos=pstrCNPJ_CPF.length-1;pos>=0;pos--) {
				soma = soma + (pstrCNPJ_CPF.substr(pos, 1) * ind)
	            ind = ind + 1
				if (pstrCNPJ_CPF.length > 11 && ind > 9) ind = 2
			}
			resto = soma - (((soma - (soma%11)) / 11) * 11)
			if (resto < 2) {
				pstrCNPJ_CPF = pstrCNPJ_CPF + "0"
				dv = dv + "0"
			} else {
				pstrCNPJ_CPF = pstrCNPJ_CPF + '' +  (11 - resto)
				dv = dv +  '' + (11 - resto)
			}
		}
		return(dv == digito)
	}
}

function verifyInteger(strInteger) {
	var bolInteger=true;
	if (strInteger!='') {
		for (i=0;i<strInteger.length;i++) {
			if (strInteger.charAt(i) == " " || strInteger.charAt(i) == "." || strInteger.charAt(i) == "-" || strInteger.charAt(i) == "," || isNaN(strInteger.charAt(i))) bolInteger=false;
		}
		return(bolInteger);
	} else 
		return(false);
}

function verifyCodigo(strInteger) {
	var bolInteger=true;
	if (strInteger!='') {
		for (i=0;i<strInteger.length;i++) {
			if (strInteger.charAt(i) == " " || strInteger.charAt(i) == "." || strInteger.charAt(i) == "-" || strInteger.charAt(i) == "," || isNaN(strInteger.charAt(i))) bolInteger=false;
		}
		return(bolInteger);
	} else 
		return(false);
}

function verifyDateDiff(strDate01,strDate02) {//strDate01=validate / strDate02=date reference
	intDay01=strDate01.split("\/")[0];intDay02=strDate02.split("\/")[0];
	intMonth01=strDate01.split("\/")[1];intMonth02=strDate02.split("\/")[1];
	intYear01=strDate01.split("\/")[2];intYear02=strDate02.split("\/")[2];
	if (intYear01-intYear02<0)
		return(false);
	else if (intYear01-intYear02>0)
		return(true);
	else if (intYear01-intYear02==0) {
		if (intMonth01-intMonth02<0)
			return(false);
		else if (intMonth01-intMonth02>0)
			return(true);
		else if (intMonth01-intMonth02==0) {
			if (intDay01-intDay02<0)
				return(false);
			else if (intDay01-intDay02>0)
				return(true);
			else if (intDay01-intDay02==0) {
				return(true);
			}
		}
	}
}

function verifyDateDiffNow(strdata) {
	if (strdata!='') {
		if (verifyDate(strdata)){
			var datNow = new Date();
			return(verifyDateDiff(strdata,datNow.getDate()+'/'+(datNow.getMonth()+1)+'/'+datNow.getYear()));
		} else {
			return(false);
		}
	} else {
		return(true);
	}
}

function verifyDateDiffTwo(strdata0, strdata1) {
	if (strdata0!='' && strdata1!='') {
		if (verifyDate(strdata0) && verifyDate(strdata1)) {
			return(verifyDateDiff(strdata1, strdata0));
		} else {
			return(false);
		}
	} else {
		return(true);
	}
}

function verifyTEL(strTEL) {
	if (strTEL!='(nn)xxnnnnnn')
		return(strTEL.search(/\([0-9]{2}\)[0-9]{6}$/)!=-1 || strTEL.search(/\([0-9]{2}\)[0-9]{7}$/)!=-1 || strTEL.search(/\([0-9]{2}\)[0-9]{8}$/)!=-1);
	else
		return(true);
}

function verifyLink(strLink){
	return(strLink.search('http://')!=-1);
}

function LimitTextArea() { // Limita caracteres no textarea

    Campo = document.getElementById("mensagem");

    Display = document.getElementById("contador");

    Caracteres = 254 - Campo.value.length;

    Display.innerHTML = Caracteres;

    if(Campo.value.length >= 254){

        Campo.value = Campo.value.substring(0, 254);
    }
}
