var blnIsNetscape=eval(navigator.appName=="Netscape");
if (blnIsNetscape) document.captureEvents(Event.KEYPRESS);

arrSettings=new Array();
arrRules=new Array();

function set(objField,strRules,strName) { 
	arrSettings[arrSettings.length]=new Array(objField,strRules,strName);
}
function verifyForm(objForm) { //Function that verifies datatype consistence and other rules, defined by the set() function, of a form. Returns true if the form is ok to be submitted, false otherwise
	loadSettings(); //Just executes the set() statements, which are defined on the page
		for (intField=0;intField<arrSettings.length;intField++) { //Go through all form items
			arrRules=arrSettings[intField][1].split(";"); //The rules for a field are in an array containing fieldobject,rules_separated_by_commas. Split the rules.
			for (intRule=0;intRule<arrRules.length;intRule++) { //Go through the rules...
				strRule=trim(arrRules[intRule]);
				if (strRule.indexOf(":")>-1) { // A kind of rule that has parameters, get its name and value
					strRuleName=strRule.split(":")[0];
					strRuleValue=strRule.split(":")[1];
				}
				else {
					strRuleName=strRule;
					
					strRuleValue="";
				}
				switch (strRuleName) { //Switch the type of rule
					case "required"://Ok
						if (getFieldValue(arrSettings[intField][0]).replace(" ","")=="") {
							alert("O campo " + arrSettings[intField][2] + " é de preenchimento obrigatório");
							arrSettings[intField][0].focus();
							return(false);
						}
						break;
					case "email":
						if (!verifyMail(trim(getFieldValue(arrSettings[intField][0])),'E-mail inválido')) {arrSettings[intField][0].focus(); return(false);}
						break;
					//In this case, "Name" parameter will be used to pass the acceptable file types
					case "cpf":
						if (!CheckCNPJCPF(trim(getFieldValue(arrSettings[intField][0])))) { alert('O campo ' + arrSettings[intField][2] + ' não foi preenchido corretamente');arrSettings[intField][0].focus(); return(false);}
						break;
					case "file":
						if (!checkFileType(arrSettings[intField][0],strRuleValue)) return(false);
						break;
					case "length":
						if (!verifyLength(strRuleValue,strRuleValue,arrSettings[intField][0],arrSettings[intField][2])) return(false);
						break;
					case "lengthRange":
						intMinLength=strRuleValue.split("~")[0];
						intMaxLength=strRuleValue.split("~")[1];
						if (!verifyLength(intMinLength,intMaxLength,arrSettings[intField][0],arrSettings[intField][2])) return(false);
						break;
					case "lengthMin":
						if (!verifyLength(strRuleValue,"",arrSettings[intField][0],arrSettings[intField][2])) return(false);
						break;
					case "lengthMax":
						if (!verifyLength("",strRuleValue,arrSettings[intField][0],arrSettings[intField][2])) return(false);
						break;
					default:
						alert("Warning: rule " + strRuleName + " of unknown type");
					case "date":
						if (verifyDate(arrSettings[intField][0])=="error") {
							arrSettings[intField][0].focus();
							alert("O campo "+arrSettings[intField][2]+ " contém uma data inválida");
							return(false);
						}
						break;
          case "compare":
           if (getFieldValue(eval(strRuleValue))!=getFieldValue(arrSettings[intField][0]))
            {
              alert("Por favor, o campo Senha e confirmação de senha deverão conter os mesmos dados.");
              arrSettings[intField][0].focus();
              return(false);
            }
						break;
				}
			}
			if (!verifyDataType(arrSettings[intField][0],arrSettings[intField][2])) return(false);
	}
	return(true);
}

function verifyDataType(objField,strLabel) {
	strDataType=getFieldType(objField);
	strFieldValue=getFieldValue(objField);
	switch (strDataType) {
		case "bte":
			if (isNaN(strFieldValue)) {
				alert("O campo " + strLabel + " deve conter um valor numérico");
				objField.focus();
				return(false);
			}
			break;
		case "int":
			if (isNaN(strFieldValue)) {
				alert("O campo " + strLabel + " deve conter um valor numérico");
				objField.focus();
				return(false);
			}
			break;
		case "lng":
			if (isNaN(strFieldValue)) {
				alert("O campo " + strLabel + " deve conter um valor numérico");
				objField.focus();
				return(false);
			}
			break;
		case "dbl":
			if (isNaN(strFieldValue.replace(",","."))) {
				alert("O campo " + strLabel + " deve conter um valor numérico");
				objField.focus();
				return(false);
			}
			break;
		case "cur":
			strDblValue=strFieldValue.replace(".","");
			strDblValue=strDblValue.replace(",",".");
			if (isNaN(strDblValue)) {
				alert("O campo " + strLabel + " deve conter um valor numérico (formato aceito: 88,88)");
				objField.focus();
				return(false);
			}
			break;
		case "dat":
			if (!verifyDate(objField)) return(false);
			break;
		default:
	}
	return(true);
}

function verifyLength(intMinLength,intMaxLength,objField,strLabel) { //Check the size of a field's value
	strFieldValue=getFieldValue(objField);
	intLength=strFieldValue.length;
	if (intMinLength=="" || intMinLength==null) { //Just max
		if (intLength>intMaxLength) {
			alert("O campo " + strLabel + " pode conter no máximo " + intMaxLength + " caracteres");
			objField.focus();
			return(false);
		}
	}
	else if (intMaxLength=="" || intMaxLength==null) { //Just min
		if (intLength<intMinLength) {
			alert("O campo " + strLabel + " deve conter no mínimo " + intMinLength + " caracteres");
			objField.focus();
			return(false);
		}
	}
	else if (intMinLength==intMaxLength) { //Fixed value
		if (intLength!=intMinLength) {
			alert("O campo " + getFieldName(objField) + " deve conter " + intMinLength + " caracteres");
			objField.focus();
			return(false);
		}
	}
	else { //Range
		if (strValue.length<intMinLength || strValue.length>intMaxLength) {
			alert("O campo " + getFieldName(objField) + " deve conter no mínimo " + intMinLength + " e no máximo " + intMaxLength + " caracteres");
			objField.focus();
			return(false);
		}
	}	
	return(true);
}
function getFieldValue(objField) { //Just cause combos don't have a value in Netscape
	if (objField.type=="select-one") return (objField.options[objField.selectedIndex].value);
	else return(objField.value);
}
function getFieldType(objField) { //Just return the three first characters of the field's name
	return(objField.name.substr(0,3));//pega os primeiros três caracteres do nome do campo (o tipo de dados.)
}

function getFieldName(objField) { //Just return the three first characters of the field's name
	return(objField.name);
}

function maskField(objField) { //Avoid invalid chars from being typed on a field (IE only)
	intKeyCode=event.keyCode;
	strTypedChar=String.fromCharCode(intKeyCode);
	if (!verifyField(strTypedChar))	return(false);
	return(true);
}
//objField --> form field to be validated;
//strFileTypes --> acceptable types of file separeted by pipes ('gif|jpg|bmp').
function checkFileType(objField,strFileTypes) {
	var strValue = objField.value;
	var strSuffix = strValue.substr(strValue.lastIndexOf('.')+1);
	var arrFileTypes = strFileTypes.split('|');
	var intField;
	var intResult = 0;
	for (intField=0;intField<arrFileTypes.length;intField++) {
		if(strSuffix!=arrFileTypes[intField]) {
			intResult++;
		}
	}
	if(intResult==arrFileTypes.length) {
		alert("Tipo de arquivo inválido!");
		objField.focus();
		return(false);
	} else {
		return(true);
	}
}
function verifyMail(strEmail,strErrorMsg) {
	strValidChars="@abcdefghijklmnopqrstuvxywzABCDEFGHIJKLMNOPQRSTUVXYWZ0123456789-_."; //Characters that an email can contain. (i'm not completely sure about it, but I didn't found any specification that could help)
	arrBoundaryChars=new Array();
	for (intPos=0;intPos<strEmail.length;intPos++) { //Check if all characters are valid
		strThisChar=strEmail.substr(intPos,1);
		if (strValidChars.indexOf(strThisChar)==-1) {
			alert(strErrorMsg);
			return(false);
		}
		if (strThisChar=="@" || strThisChar==".") { //Feed the BoundaryChars array
			arrBoundaryChars[arrBoundaryChars.length]=parseInt(intPos);
		}		
	}
	if (navigator.appName!="Netscape") {
		for (intPos=0;intPos<arrBoundaryChars.length;intPos++) { //Check if dots and ats are not in conflict
			intThisItem=arrBoundaryChars[intPos]
			intNextItem=(intPos==arrBoundaryChars.length) ? 0 : arrBoundaryChars[intPos+1]
			if (intThisItem==0 || intThisItem==strEmail.length-1) {
				alert(strErrorMsg);
				return(false);
			}
			if (intThisItem+1==intNextItem) {
				alert(strErrorMsg);
				return(false);
			}
		}
	}
	intFirstAtIndex=strEmail.indexOf("@");
	intLastAtIndex=strEmail.lastIndexOf("@");
	intFirstDotIndex=strEmail.indexOf(".");
	intLastDotIndex=strEmail.lastIndexOf(".");
	
	if (intFirstAtIndex!=intLastAtIndex || intFirstAtIndex==-1 || intFirstDotIndex==-1 || intLastDotIndex<intFirstDotIndex) {
		alert(strErrorMsg);
		return(false);
	}
	return(true); //If it got here, it's all ok (I hope)
}

function replaceThatWorks(strValue,strSearch,strReplace) {
	var strResult = new String(strValue);
	var strBefore, strAfter;
	while(strResult.indexOf(strSearch)!=-1) {
		strBefore = strResult.substring(0,strResult.indexOf(strSearch));
		strAfter = strResult.substring(strResult.indexOf(strSearch)+1,strResult.length);
		strResult = strBefore + strReplace + strAfter
	}
	return(strResult);
}

function CheckCNPJCPF(cgc) {
  var cgc = String(cgc);
	cgc = replaceThatWorks(cgc,'.','');
	cgc = replaceThatWorks(cgc,'-','');
	cgc = replaceThatWorks(cgc,'/','');
  if (cgc.length==11) { 
    if (cgc == "00000000000" || cgc == "11111111111" ||
      cgc == "22222222222" ||	cgc == "33333333333" || cgc == "44444444444" ||
		  cgc == "55555555555" || cgc == "66666666666" || cgc == "77777777777" ||
		  cgc == "88888888888" || cgc == "99999999999")
		  return false;
      
	  soma = 0;
    
	  for (i=0; i < 9; i ++)
		  soma += parseInt(cgc.charAt(i)) * (10 - i);
      
	  resto = 11 - (soma % 11);
     
	  if (resto == 10 || resto == 11)
	  	resto = 0;
      
	  if (resto != parseInt(cgc.charAt(9)))
		  return false;
      
	  soma = 0;
    
	  for (i = 0; i < 10; i ++)
	    soma += parseInt(cgc.charAt(i)) * (11 - i);
      
	  resto = 11 - (soma % 11);
    
	  if (resto == 10 || resto == 11)
		  resto = 0;
   
	  if (resto==parseInt(cgc.charAt(10)))
		  return true;
    else
      return false;
  }
  else
  {
    if (cgc.length==14 && parseInt(cgc)>0) {
      var1 = 0;
      i = 0;
      var4 = 0;
      var5 = 0;
      var2 = 5;
    
      for (i=0; i < 12; i ++)
      {
        var1 += parseInt(cgc.charAt(i)) * var2;
      
        if (var2>2)
          var2=var2-1;
        else
          var2=9;
      }
    
      var1=(var1 % 11);
    
      if (var1 > 1)
        var4 =11 - var1;
      else
        var4=0;
     
      var1 = 0;
      i = 0;
      var2 = 6;
    
      for (i=0; i < 13; i ++) {
        var1 += parseInt(cgc.charAt(i)) * var2;
        if (var2>2)
          var2=var2-1;
        else
          var2=9;
      }
    
      var1 = (var1 % 11);
    
      if (var1>1)
        var5=11-var1;
      else
        var5=0;
       
      if (var4==parseInt(cgc.charAt(12)) && var5==parseInt(cgc.charAt(13)))
        return true;
      else
        return false;  

    }
    else 
     return false;
  }     
}

//Função do Pedro que verifica data.
//function verifyDate(objField) {
//	strDate=getFieldValue(objField);
//	if (strDate.indexOf("/")==strDate.lastIndexOf("/")){ // se houver menos que duas barras caia fora
//		//alert("data inválida")
//		return(false)
//	}
//	day=strDate.substr(0,strDate.indexOf("/"))
//	month=strDate.substr(strDate.indexOf("/")+1,strDate.lastIndexOf("/")-strDate.indexOf("/")-1)
//	year=strDate.substr(strDate.lastIndexOf("/")+1,strDate.length-strDate.lastIndexOf("/")-1)
//	if (isNaN(day) || isNaN(month) || isNaN(year)) {
//		//alert("data inválida. formato aceito: dd/mm/aaaa")
//		return(false)
//	}//Inserir Validação de campo e validação de mês
///	if (day<1 || day>31 || month<1 || month>12 || year<1800 || year>2200) {
	//	//alert("data inválida")
//		return(false)
//	}
//	return(true)
//}

//To do: re-write the date validation and add more rules

function trim(str) {
	var startIndex,endIndex,returnValue
	for (i=0;i<str.length;i++) {
		atChar=str.substring(i,1)
		if (atChar!=" " && atChar!="\n" && atChar!="\r" && atChar!="\t") {
			startIndex=i
			break
		}
	}
	for (i=str.length-1;i>=0;i--) {
		atChar=str.substring(i,1)
		if (atChar!=" " && atChar!="\n" && atChar!="\r" && atChar!="\t") {
			endIndex=i
			break
		}
	}
	return(str.substring(startIndex,endIndex+1))
}
//Função que verifica a validez de datas.
function verifyDate(objDate){
 	var datDate = objDate.value ;
	
	if (datDate==""){return("ok");}
	
	var intNumDate = datDate.replace("/","");
	var intDay = datDate.substr(0,2);
	var intMonth = datDate.substr(3,2);	
	var intYear = datDate.substr(6,4);
	var bytYearBissexto = "false";
	
	//Verifica se os valores de dia, mês e ano são valores numéricos
	if (isNaN(intDay)) {return("error");}
	if (isNaN(intMonth)){return("error");}
	if (isNaN(intYear)) {return("error");}
	
	// Verifica formatação
	var objLenthYear = datDate.substr(6,4)
	var intAnoIntervalo = eval(datDate.substr(6,4))/1000
	if (intAnoIntervalo < 1) {
			return("error");
	}
	if (isNaN(datDate.substr(0,2)) || datDate.substr(2,1)!="/" || isNaN(datDate.substr(3,2)) || datDate.substr(5,1)!="/" ||  isNaN(datDate.substr(6,4)) ||  isNaN(datDate.substr(9,1)) || eval(objLenthYear.length)<4){
			return("error");
	}
	
	//Verifica se o mês é válido.
	if (intMonth<1 || intMonth>12){
			return("error");
	}
	
	//verifica se o ano é bissexto.
	if (intYear%4==0) bytYearBissexto = "true";
	
	//Verifica se o dia é correto.
	switch (eval(intMonth)) {
	case 1:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	case 2:
			if (bytYearBissexto=="true"){	//Ano bissexto.
			if (eval(intDay)<1 || eval(intDay)>29){
				return("error");
			}
		
		}
		else
		{
		if (eval(intDay)<1 || eval(intDay)>28){
				return("error");
			}
		}
		break;
		case 3:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	case 4:
		if (eval(intDay)<1 || (intDay)>30){
			return("error");
		}
		break;
	case 5:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	case 6:
		if (eval(intDay)<1 || (intDay)>30){
			return("error");
		}
		break;
	case 7:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	case 8:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	case 9:
		if (eval(intDay)<1 || (intDay)>30){
			return("error");
		}
		break;
	case 10:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	case 11:
		if (eval(intDay)<1 || (intDay)>30){
			return("error");
		}
		break;
	case 12:
		if (eval(intDay)<1 || (intDay)>31){
			return("error");
		}
		break;
	}
	return("ok");//Se chegou até aqui a data é válida.	
}
