/* Constants definition */
function GetIntegerMaxValue() { return 2147483647; } // Int32 maximum value
function GetIntegerRE() { return "^[0-9]+$"; } // Integer pattern
function GetEmailRE() { return "^[\\w\\-]+(\\.[\\w\\-]+)*@[\\w\\-]+(\\.[\\w\\-]+)*\\.[\\w\\-]{2,}$"; } // EMail pattern : something[.something]@something[.something.something].[something]
function GetDateRE() { return "^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[0-2])/[12][0-9]{3}$"; } // Date pattern : DD/MM/YYYY where DD between 01 and 31, MM between 01 and 13, YYYY between 2000 and 2999
function GetUrlRE() { return "^(http://|https://){0,1}[A-Za-z0-9][A-Za-z0-9\-\.]+[A-Za-z0-9]\.[A-Za-z]{2,}[\43-\176]*$"; }
function GetPhoneRE() { return "^[+]?[0-9 ]*[(]?[0-9 ]+[)]?[0-9 .\\-/]+$"; }
function GetHourRE() { return "^([0-1][0-9]||[2][0-3])[:]([0-5][0-9])$"; }
function GetVatRE() { return "^((([A-Z]{2}[ \.\-]?)?(([0-9]{2}|0)[\-]?)?[0-9]{3}[\-]?[0-9]{3}[\-]?[0-9]{3})|((([A-Z]{2}[ \.\-]?)?(([0-9]{2}|0)[\.]?)?[0-9]{3}[\.]?[0-9]{3}[\.]?[0-9]{3}))|((([A-Z]{2}[ \.\-]?)?(([0-9]{2}|0)[ ]?)?[0-9]{3}[ ]?[0-9]{3}[ ]?[0-9]{3})))$"; }
// ^([A-Z]{2}[ \.\-])?(([0-9]{2}|0)[ \.\-]?)?[0-9]{3}[ \.\-]?[0-9]{3}[ \.\-]?[0-9]{3}$
/* Tools */
function GetFullYear(year) 
{
	if ((Math.abs(year) + "").length < 4) year += 1900;
	return year;
}

function Now()
{
	/* Return today as DD/MM/YYYY */
	
	var today = new Date();
	var day = today.getDate();
	var month = today.getMonth() + 1;
	var year = GetFullYear(today.getYear());

	var dayStr = (day + "").length < 2 ? "0" + day : day + "";
	var monthStr = (month + "").length < 2 ? "0" + month : month + "";
		
	return dayStr + "/" + monthStr + "/" + (year + "");
}

function yyyymmdd(date)
{
	/* Convert the date as a string under format YYYYMMDD */
	
	var dateFormatted = "";
	
	if (IsDateValid(date))
	{
		var dateSplitted = date.split("/");
		
		var year = GetFullYear(dateSplitted[2]);
		var month = dateSplitted[1].length < 2 ? "0" + dateSplitted[1] : dateSplitted[1];
		var day = dateSplitted[0].length < 2 ? "0" + dateSplitted[0] : dateSplitted[0];

		dateFormatted =  year + month + day;
	}
	
	return dateFormatted;
}

/* Check functions */
function IsVat(vatValue)
{
	var regExp = new RegExp(GetVatRE(), "");
	return regExp.test(vatValue);
}

function IsInteger(nbrValue)
{
	var regExp = new RegExp(GetIntegerRE(), "");
	return regExp.test(nbrValue) && (nbrValue <= GetIntegerMaxValue());
}

function IsCurrency(nbrValue)
{
	return IsInteger(nbrValue);
}

function IsEmail(emailValue)
{
	var regExp = new RegExp(GetEmailRE(), "i");
	return regExp.test(emailValue);
}

function IsDate(dateValue)
{
	var regExp = new RegExp(GetDateRE(), "");
	return regExp.test(dateValue);
}

function IsPhone(phoneValue)
{
	var regExp = new RegExp(GetPhoneRE(), "");
	return regExp.test(phoneValue);
}

function IsHour(hourValue)
{
	var regExp = new RegExp(GetHourRE(), "");
	return regExp.test(hourValue);
}

function IsDateValid(dateValue)
{
	var result = true;
	
	if (IsDate(dateValue))
	{
		var dateSplitted = dateValue.split("/");
		var dateComposed = new Date(dateSplitted[2], dateSplitted[1] - 1, dateSplitted[0]);
		var year = GetFullYear(dateComposed.getYear());

		result = ((dateComposed.getDate() == dateSplitted[0]) && (dateComposed.getMonth() == (dateSplitted[1] - 1)) && (year == dateSplitted[2]));
	}
	else
		result = false;
	
	return result;
}

function CheckText(field, operation, textValue)
{
	var result = true;
	
	switch (operation)
	{
	case ("==") :
		return (field.value == textValue);
	break;
	case ("!=") :
		return (field.value != textValue);
	break;
	}
	
	return result;
}

function CheckDualCheckBoxes(field, operation, checked_1, checked_2)
{
	var result = true;
	
	switch (operation)
	{
	case ("||") :
		result = (checked_1 || checked_2);
	break;
	}
	
	return result;
}

function CheckDate(date, operation, lowerBound, higherBound)
{
	/* if operation is "<" or "<=" and higherBound == "" then higherBound = today */
	/* if operation is ">" or ">=" and lowerBound == "" then lowerBound = today */
		
	var result = IsDateValid(date.value);
	
	if (result)
	{
		switch (operation) 
		{
		case ("<") : // Check date is lower than higherBound
			if ((higherBound == "") || (higherBound == null)) higherBound = Now();
			if (IsDateValid(higherBound)) result = (yyyymmdd(date.value) < yyyymmdd(higherBound));
			break;
		case ("<=") : // Check date is lower or equal than higherBound
			if ((higherBound == "") || (higherBound == null)) higherBound = Now();
			if (IsDateValid(higherBound)) result = (yyyymmdd(date.value) <= yyyymmdd(higherBound));
			break;
		case (">") : // Check date is greater than lowerBound
			if ((lowerBound == "") || (lowerBound == null)) lowerBound = Now();
			if (IsDateValid(lowerBound)) result = (yyyymmdd(date.value) > yyyymmdd(lowerBound));
			break;
		case (">=") : // Check date is greater or equal than lowerBound
			if ((lowerBound == "") || (lowerBound == null)) lowerBound = Now();
			if (IsDateValid(lowerBound)) result = (yyyymmdd(date.value) >= yyyymmdd(lowerBound));
			break;
		case ("[]") : // Check date is higher or equal than lowerBound and lower or equal than higherBound
			if ((IsDateValid(lowerBound)) && (IsDateValid(higherBound))) result = ((yyyymmdd(date.value) >= yyyymmdd(lowerBound)) && (yyyymmdd(date.value) <= yyyymmdd(higherBound)));
			break;
		}
	}
	
	return result;
}

function CheckInteger(field, operation, lowerBound, higherBound)
{
	var result = IsInteger(field.value);

	if (result)
	{	
		var valueAsInt = field.value * 1;
		var lowerBoundAsInt = lowerBound * 1;
		var higherBoundAsInt = higherBound * 1;
		
		switch (operation)
		{
		case (">") :
			result = (valueAsInt > lowerBoundAsInt);
		break;
		case (">=") :
			result = (valueAsInt >= lowerBoundAsInt);
		break;
		case ("[]") :
			result = ((valueAsInt >= lowerBoundAsInt) && (field.value <= higherBoundAsInt))
		break;
		}	
	}
	
	return result;
}

function CheckCurrency(field, operation, lowerBound, higherBound)
{
	var result = IsCurrency(field.value);

	var valueAsInt = field.value * 1;
	var lowerBoundAsInt = lowerBound * 1;
	var higherBoundAsInt = higherBound * 1;

	if (result)
	{	
		switch (operation)
		{
		case (">=") :
			result = (valueAsInt >= lowerBoundAsInt);
		break;
		}	
	}
	
	return result;
}

function IsEmpty(fieldValue)
{
	return (fieldValue == "");
}

function IsUrl(urlValue) 
{
	var regExp = new RegExp(GetUrlRE(), "i");
	return regExp.test(urlValue);
}

function SetError(fieldObj)
{
	fieldObj.style.backgroundColor = '#FFB6C1';
}

function SetValid(fieldObj)
{
	fieldObj.style.backgroundColor = '';
}

function SetAllValid()
{
	if (arrayOfFields != null)
		for (idx = 0; idx < arrayOfFields.length; SetValid(arrayOfFields[idx++][0]));
}

/* Messages functions */
var fieldsErrorList = new Array();
var message = "";

function ResetFieldsErrorList()
{
	fieldsErrorList = new Array();
}

function SetFieldsErrorList(fieldName)
{
	var idx;
	var found = false;
	
	for (idx = 0; idx < fieldsErrorList.length; idx++)
		if (fieldsErrorList[idx] == fieldName)
		{
			found = true;
			break;
		}

	if (!found)		
		fieldsErrorList[fieldsErrorList.length] = fieldName;
}

function GetMessage(errorMessageSingular, errorMessagePlural)
{
	return fieldsErrorList.length > 0 ? (fieldsErrorList.length > 1 ? errorMessagePlural : errorMessageSingular) + fieldsErrorList.join(", ") : "";
}

/* Fields to check */
var arrayOfFields;

function ResetArrayOfFields()
{
	arrayOfFields = new Array();
	arrayOfFieldsCount = 0;
}

function CheckAlreadyAdded(fieldName)
{
	var found = false;
	
	for (idx = 0; idx < arrayOfFields.length; idx++)
	{
		if (arrayOfFields[idx][0] == fieldName)
		{
			found = true;
			break;
		}
	}
	
	return found;
}

function AddField(fieldName, type, mandatory, check, fieldDescription, operation, lowerBound, higherBound)
{
	if (arrayOfFields == null) arrayOfFields = new Array();

	var idx = arrayOfFields.length;

	if (fieldName)
	{
		if (!CheckAlreadyAdded(fieldName))
		{
			arrayOfFields[idx] = new Array();
			arrayOfFields[idx][0] = fieldName;
			arrayOfFields[idx][1] = type;
			arrayOfFields[idx][2] = mandatory;
			arrayOfFields[idx][3] = check;
			arrayOfFields[idx][4] = fieldDescription;
			arrayOfFields[idx][5] = operation;
			arrayOfFields[idx][6] = lowerBound;
			arrayOfFields[idx][7] = higherBound;
		}
	}
}

function CheckField(field, type, mandatory, check, fieldDescription, operation, lowerBound, higherBound)
{
	var result = true;

	if (check)
	{
		switch (type)
		{
		case ("TEXT") :
			result = mandatory ? !IsEmpty(field.value) : true;
			
			if ((result) && (operation != null) && (operation != "") && (field.value != null))
				result = CheckText(field, operation, lowerBound);
		break;
		case ("EMAIL") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = IsEmail(field.value);
		break;
		case ("DATE") :
			var emptyField = IsEmpty(field.value);
			
			result = mandatory ? !emptyField : true;
			
			if (result && !emptyField)
				result = CheckDate(field, operation, lowerBound, higherBound);
		break;
		case ("URL") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = IsUrl(field.value);
		break;
		case ("DUALCHECKBOXES") :
			if ((operation != null) && (operation != ""))
				result = CheckDualCheckBoxes(field, operation, lowerBound, higherBound);
		break;
		case ("INTEGER") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = CheckInteger(field, operation, lowerBound, higherBound);
		break;
		case ("CURRENCY") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = CheckCurrency(field, operation, lowerBound, higherBound);
		break;
		case ("PHONE") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = IsPhone(field.value);
		break;
		case ("HOUR") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = IsHour(field.value);
		break;
		case ("VAT") :
			if ((mandatory) || (!IsEmpty(field.value)))
				result = IsVat(field.value);
		break;
		}
	}

	if (!result)
	{
		SetError(field);
		SetFieldsErrorList(fieldDescription);
	}
	else
		SetValid(field);

	return result;
}

function CheckFields() 
{
	var idx;
	var result = true;

	for (idx = 0; idx < arrayOfFields.length; idx++)
	{	
		var tmp = CheckField(arrayOfFields[idx][0], arrayOfFields[idx][1], arrayOfFields[idx][2], arrayOfFields[idx][3], arrayOfFields[idx][4], arrayOfFields[idx][5], arrayOfFields[idx][6], arrayOfFields[idx][7]);
		
		if (result) 
			result = tmp;
	}
	
	return result;
}

