// -----------------------------------------------------------------------------
// Initializing script - setting global variables
// -----------------------------------------------------------------------------
var list_of_errors; 				// Keeps the list of errors.
var checkObjects = new Array(); 	// Array containing the objects to validate.
validationMsg = new Object();
validationMsg.header			= "Atenção:"
validationMsg.start				= ">> ";
validationMsg.require			= " é requerido(a)";
validationMsg.and				= " e";
validationMsg.minNum			= " desde ";
validationMsg.maxNum			= " até ";
validationMsg.num				= " apenas números";
validationMsg.file				= ". Pressione [Browse] para selecionar um ficheiro localmente";
validationMsg.minChars			= " um mínimo de ";
validationMsg.maxChars			= " até ";
validationMsg.chars				= " caractéres";
validationMsg.must				= " deve conter";
validationMsg.email				= " um endereço válido";
validationMsg.cpostal			= " o formato 9999 XXXX ou 9999-999 XXXX";
validationMsg.numcontribuinte	= " um número válido";
validationMsg.url				= " um endereço de Web válido";

// -----------------------------------------------------------------------------
// formName 	= name of form										- Required
// fieldName 	= name of the input field 							- Required
// fieldRequired= is the field required? (0 or 1)					- Required
// fieldType 	= string, num, email, cpostal, numcontribuinte		- Required
// fieldNameExt = real name of field to show on error message 		- Required
// min 			= the strings must have at least xx chars
//				  or numbers have a lower limit of xx (not chars)	- Optional (type undefined, when a maximum value is needed)
// max 			= the value must have a maximum of xx chars
//				  or numbers an upper limit of xx (not chars)		- Optional
// -----------------------------------------------------------------------------
function defineValidation(formName, fieldName, fieldRequired, fieldType, fieldNameExt, min, max)
{
	checkObjects[checkObjects.length] = new fieldDescription(formName, fieldName, fieldRequired, fieldType, fieldNameExt, min, max);
}

// -----------------------------------------------------------------------------
// fieldDescription - Used internally to create the objects
// -----------------------------------------------------------------------------
function fieldDescription(formName, fieldName, fieldRequired, fieldType, fieldNameExt, min, max)
{
	this.formName = formName;
	this.fieldName = fieldName;
	this.fieldRequired = fieldRequired;
	this.fieldType = fieldType;
	this.fieldNameExt = fieldNameExt;
	this.min = min;
	this.max = max;
}

// -----------------------------------------------------------------------------
// add_message_num - Used internally to generate error messages for numeric fields
// -----------------------------------------------------------------------------
function add_message_num(i)
{
	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt;
	list_of_errors += (checkObjects[i].fieldRequired ? validationMsg.require + validationMsg.and : "");
	list_of_errors += validationMsg.must + validationMsg.num;

	if (isFinite(checkObjects[i].min))				// if lower limit defined
	{
		list_of_errors += validationMsg.minNum + checkObjects[i].min;
	}
	if (isFinite(checkObjects[i].max))				// if upper limit defined
	{
		list_of_errors += validationMsg.maxNum + checkObjects[i].max;
	}
	list_of_errors += "\n";
}

// -----------------------------------------------------------------------------
// check_num - Used internally to check numeric fields
// -----------------------------------------------------------------------------
function check_num(i, objecto)
{
	var error, valor = objecto.value;

	if (! valor)				// if field is empty
	{
		error = checkObjects[i].fieldRequired;	// and required, error is set to true
	}
	else if (isFinite(valor))	// if is a number and not within limits, error is set to true
	{
		error = isFinite(checkObjects[i].min) && valor < checkObjects[i].min ||
				isFinite(checkObjects[i].max) && valor > checkObjects[i].max;
	}
	else	// if it is not a number, error is set to true
	{
		error = true;
	}

	if (error)
	{
		add_message_num(i);
	}
}

// -----------------------------------------------------------------------------
// add_message_file - Used internally to generate error messages for file fields
// -----------------------------------------------------------------------------
function add_message_file(i)
{
	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt;
	list_of_errors += (checkObjects[i].fieldRequired ? validationMsg.require + validationMsg.file : "") + "\n";
}

// -----------------------------------------------------------------------------
// check_file - Used internally to check file fields
// -----------------------------------------------------------------------------
function check_file(i, objecto)
{
	var error, valor = objecto.value;

	if (! valor)
	{
		error = checkObjects[i].fieldRequired;
	}

	if (error)
	{
		add_message_file(i);
	}
}

// -----------------------------------------------------------------------------
// add_message_string - Used internally to generate error messages for string fields
// -----------------------------------------------------------------------------
function add_message_string(i)
{
	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt;
	list_of_errors += (checkObjects[i].fieldRequired ? validationMsg.require : "");

	// if minimum or maximum number of chars is defined, checks if string is required
	// if it is, adds an 'and' before the min/max chars message
	if (isFinite(checkObjects[i].min) || isFinite(checkObjects[i].max))
	{
		list_of_errors += (checkObjects[i].fieldRequired ? validationMsg.and : "") + validationMsg.must;
	}
	if (isFinite(checkObjects[i].min))		// if minimum number of chars is defined
	{
		list_of_errors += validationMsg.minChars + checkObjects[i].min + validationMsg.chars;
	}
	if (isFinite(checkObjects[i].max))		// if maximum number of chars is defined
	{
		list_of_errors += validationMsg.maxChars + checkObjects[i].max + validationMsg.chars;
	}
	list_of_errors += "\n";
}

// -----------------------------------------------------------------------------
// check_string - Used internally to check string fields
// -----------------------------------------------------------------------------
function check_string(i, objecto)
{
	var error, valor = objecto.value;

	if (! valor)
	{
		error = checkObjects[i].fieldRequired;
	}
	else	// if field is filled, check if length is within limits. if not, error is set to true
	{
		error = isFinite(checkObjects[i].min) && valor.length < checkObjects[i].min ||
				isFinite(checkObjects[i].max) && valor.length > checkObjects[i].max;
	}

	if (error)
	{
		add_message_string(i);
	}
}

// -----------------------------------------------------------------------------
// add_message_email - Used internally to generate error messages for email fields
// -----------------------------------------------------------------------------
function add_message_email(i)
{
   	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt + (checkObjects[i].fieldRequired ? validationMsg.require + validationMsg.and : "") + validationMsg.must + validationMsg.email + "\n";
}

// -----------------------------------------------------------------------------
// check_email - Used internally to check email fields
// -----------------------------------------------------------------------------
function check_email(i, objecto)
{
	var error, email_addresses, valor = objecto.value;

	if (! valor)
	{
		error = checkObjects[i].fieldRequired;
	}
	else	// tests email contents with regexp
	{
		email_addresses = valor + "\r\n";

		re = /^([0-9a-z]+([._-][0-9a-z]+)*@(([0-9a-z]+([._-][0-9a-z]+)*(\.[a-z]{2,3}))|(([0-9]{1,3}\.){3}([0-9]{1,3})))(\r\n)+)*$/i;

		error = ! re.test(email_addresses);
	}

	if (error)
	{
		add_message_email(i);
	}
}

// -----------------------------------------------------------------------------
// add_message_url - Used internally to generate error messages for URL fields
// -----------------------------------------------------------------------------
function add_message_url(i)
{
   	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt + (checkObjects[i].fieldRequired ? validationMsg.require + validationMsg.and : "") + validationMsg.must + validationMsg.url + "\n";
}

// -----------------------------------------------------------------------------
// check_url - Used internally to check URL fields
// -----------------------------------------------------------------------------
function check_url(i, objecto)
{
	var error, valor = objecto.value;

	if (! valor)
	{
		error = checkObjects[i].fieldRequired;
	}
	else	// tests url contents with regexp. values like just 'http://' are valid
	{
		re = /^((ht|f)tp:\/\/)?([0-9a-z]+\@[0-9a-z]+:)?((([0-9a-z]+([._-][0-9a-z]+)*(\.[a-z]{2,3}))|(([0-9]{1,3}\.){3}([0-9]{1,3})))(:\d{1,4})?){1}(\/?|(\/(~?[0-9a-z]+\/?)*([#%&_+=?.-][0-9a-z]+)*))$/i;
		error = ! re.test(valor);
	}

	if (error)
	{
		add_message_url(i);
	}
	else
	{
		valor = valor.toLowerCase();		// converts to lowercase

		if (valor.length > 4 && valor.substring(0, 4) != 'http')
		{
			objecto.value = 'http://' + valor		// adds http:// prefix if necessary
		}
	}
}

// -----------------------------------------------------------------------------
// add_message_cpostal - Used internally to generate error messages for postal code fields
// -----------------------------------------------------------------------------
function add_message_cpostal(i)
{
	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt + (checkObjects[i].fieldRequired ? validationMsg.require + validationMsg.and : "") + validationMsg.must + validationMsg.cpostal + "\n";
}

// -----------------------------------------------------------------------------
// check_cpostal - Used internally to check postal code fields
// -----------------------------------------------------------------------------
function check_cpostal(i, objecto)
{
	var error, valor = objecto.value;

	if (! valor)
	{
		error = checkObjects[i].fieldRequired;
	}
	else	// tests postal code contents with regexp
	{
	   	re = /^\d{4}[ ]?(-[ ]?\d{3})?[ ]([\wàèìòùáéíóúãõâêôç]+([-.ºª]?[ ]?[\wàèìòùáéíóúãõâêôç]+)*)+$/i;

		error = ! re.test(valor);
	}

	if (error)
	{
		add_message_cpostal(i);
	}
}

// -----------------------------------------------------------------------------
// add_message_numcontribuinte - Used internally to generate error messages for "numeros contribuintes"
// -----------------------------------------------------------------------------
function add_message_numcontribuinte(i)
{
	list_of_errors += validationMsg.start + checkObjects[i].fieldNameExt + (checkObjects[i].fieldRequired ? validationMsg.require + validationMsg.and : "") + validationMsg.must + validationMsg.numcontribuinte + "\n";
}

// -----------------------------------------------------------------------------
// check_numcontribuinte - Used internally to check "numeros contribuintes"
// -----------------------------------------------------------------------------
function check_numcontribuinte(i, objecto)
{
	var error, s = 0, x = "", valor = objecto.value;
 
 	if (! valor || valor && valor.length > 9)
	{
		error = checkObjects[i].fieldRequired;
	}
	else
	{
		if (valor.length < 9)
		{
			x = x + Math.pow(10, (9 - valor.length));
			valor = x.substring(1) + valor;
		}
		for (var p = 0; p < 8; p++)
		{
			s = s + (9 - p) * parseInt(valor.substring(p, p + 1));
		}

		s = s % 11;

		s = (s < 2 ? 0 : 11 - s);

		if (s > 9)
		{
			s = 0;
		}

		error = (s != parseInt(valor.substring(8, 9)));
	}

	if (error)
	{
		add_message_numcontribuinte(i);
	}
}

// -----------------------------------------------------------------------------
// validate - Call this function on submit button (onClick="return validate('nameOfForm', ['realNameOfForm'])")
// realNameOfForm parameter is optional. it is very useful when there is more than one form
// with the same elements and only one form definition is necessary.
// ex:	onClick="return validate('contact', 'contact1')" for form 'contact1'
//		onClick="return validate('contact', 'contact2')" for form 'contact2'
//	'contact' is declared (ficticious), but 'contact1' and 'contact2' are checked (existent forms)
// -----------------------------------------------------------------------------
function formValidate(formName, realFormName)
{
	if (arguments.length == 1)
	{
		realFormName = formName;
	}
	list_of_errors = "";

	for(i = 0; i < checkObjects.length; i++)
	{
		if (checkObjects[i].formName == formName)	// if form is current
		{
			//objecto = eval("document." + realFormName + "." + checkObjects[i].fieldName);
			objecto = eval("document." + realFormName + ".elements['" + checkObjects[i].fieldName + "']");
			if (checkObjects[i].fieldType != 'file')
			{
				objecto.value = objecto.value.replace(/^\s+/, '');	// remove spaces, newlines and other
				objecto.value = objecto.value.replace(/\s+$/, '');	// non alphabetical chars from textbox
			}

			eval("check_" + checkObjects[i].fieldType + "(" + i + ", objecto)");	// checks appropriate field, depending on its type
		}
	}

	if (list_of_errors)	// if there is an error, shows it and returns false
	{
		alert(validationMsg.header + "\n" + list_of_errors);
		return false;
	}
	else
	{
		return true;
	}
}
