/*	
	Set of functions used to validate user input.
	Note: Utils.js must be included.
	
	Main function of this module is ValidateControls
	You must pass as argument ID's of controls to
	validate separated by comma (",") 
	Like: ValidateControls("Name,Description,Amount")
	Note: Do not put additional spaces after commas
	
	All thouse Controls require to have vType attribute
	that indicates type of validation
	Like: <input type="text" vType="Decimal">
	
	Depend on choised attribute control can have
	additional parameters, that will be used in
	validation. Some of them required
	
	Avaliable Parameters:
		- NonEmpty
			Check that control value is not empty
		- Decimal
			Check that control's value in accordance with the decimal type.
			Negative values are avaliable on level with positive values.
			Is control's value equal to empty (trimmed) string it will be
			replaced to zero.
			Additional Attributes:
				- vMinValue
					Required:	No
					Type:		Decimal
					Default:	<not set>
					Minimum possibly value
				- vMaxValue
					Required:	No
					Type:		Decimal
					Default:	<not set>
					Maximum possibly value
		- Integer
			Check type that work's like decimal but not assept dot in the value of controls
			Additional Attributes: Some as in decimal type check
		- RegEx
			Check control's value using a specified regular expression.
			Additional Attributes:
				- vRequired
					Required:	No
					Type:		Bool
					Default:	true
					Indicates that field can be empty.
				- vPattern
					Required:	Yes
					Type:		String
					Regular expression pattern that will be used to check represented value.
					Note: 
						1)Be shure that you not specify empty pattern. In that case any value
							will pass.
						2)Check that you do not foget plase begin line & end line statements if
							you need to validate whole line (not only part)
				- vMessage
					Required:	Yes
					Type:		String
					Message that will be showed in tool tip.
		- Date
			Check that control value is Date in format MM/DD/YYYY
			Additional Attributes:
				- vRequired
					Required:	No
					Type:		Bool
					Default:	true
					Indicates that field can be empty.
		- Email
			Check that control value is Email in w3org format
			Additional Attributes:
				- vRequired
					Required:	No
					Type:		Bool
					Default:	true
					Indicates that field can be empty.
		- Phone
			Check that control value is Phone in (999)999-9999 format
			Additional Attributes:
				- vRequired
					Required:	No
					Type:		Bool
					Default:	true
					Indicates that field can be empty.
				- vName
					Required:	Yes
					Type:		String
					Device that will be showed in tool tip.
					
				
	Each type can parce vTrim additional attribute.
		Required:	No
		Type:		Bulean
		Default:	true
		Value indicating then whether module must trim control value before checking
*/
var vMESSAGE_NON_DIGITAL = "Field contains non-digital characters.";
var vMESSAGE_ILLEGAL_CHARACTERS = "Field contains inadmissible characters.";
var vMESSAGE_BLANK_FIELD = "Field cannot be blank.";
var vMESSAGE_CANNOT_EXCEED = "Field value exceed {0}.";
var vMESSAGE_CANNOT_BE_LESS = "Field value less then {0}.";

var vMESSAGE_INVALID_DATE_FORMAT = "Field value is not in a valid date format.";
var vMESSAGE_INVALID_MONTH_NUMBER = "Month must be between 1 and 12.";
var vMESSAGE_INVALID_DAY_NUMBER = "Day must be between 1 and 31.";
var vMESSAGE_INVALID_DAY_NUMBER_NO31 = "Month {0} doesn't have 31 days.";
var vMESSAGE_INVALID_MONTH_FEBRUARY = "February {0} doesn't have {1} days.";

var vMESSAGE_INVALID_EMAIL = "Field value is not in a valid email format.";
var vMESSAGE_INVALID_PHONE = "Field value is not in a valid {0} format. Valid format is (999)999-9999"

function ValidateControlsShowMessage(ControlIDs, showMessage)
{
	if(typeof(UtilsIncluded) == "undefined")
		vRaiseClientError("Utils.js not included.");
	var IDs = ControlIDs.split(",");
	var res = true;
	for(var i = 0; i<IDs.length; i++)
	{
		try
		{
			var Control = SearchControl(IDs[i]);
			switch(GetAttribute(Control, "vType"))
			{
				case "NonEmpty":
					res = vValidateNonEmpty(Control) && res;
					break;
				case "Decimal":
					res = vValidateDecimal(Control) && res;
					break;
				case "Integer":
					res = vValidateInteger(Control) && res;
					break;
				case "RegEx":
					res = vValidateRegEx(Control) && res;
					break;
				case "Date":
					res = vValidateDate(Control) && res;
					break;
				case "Email":
					res = vValidateEmail(Control) && res;
					break;
				case "Phone":
					res = vValidatePhone(Control) && res;
					break;
				default:
					throw "Check type \"" + Control.vType + "\" are incorrect";
					break;
			}
		}
		catch(e)
		{
			if(typeof e == "string")
				vRaiseClientError(e + "\r\n\r\nControl ID: \"" + IDs[i] + "\"");
			else
				throw e;
		}
	}
	vRaiseValidationError(!res && showMessage)
	return res;
}

function vRaiseValidationError(showError)
{
	if(showError)
		alert('You have admitted errors. Data cannot be kept until errors will not be corrected.');
}

function ValidateControls(ControlIDs)
{
	return ValidateControlsShowMessage(ControlIDs, true)
}

function vValidateTags(Control)
{
	vTrimIfRequired(Control);
	if(Control.value.indexOf(">") > -1 || Control.value.indexOf("<") > -1)
	{
		vMarkErrorControl(Control, 	vMESSAGE_ILLEGAL_CHARACTERS);
		return false;
	}
	return true;
}
function vValidateNonEmpty(Control)
{
	if(!vValidateTags(Control))
		return false;
	if (Control.value == "")
	{
		vMarkErrorControl(Control, vMESSAGE_BLANK_FIELD);
		return false;
	}
	vMarkSucsessControl(Control);
	return true;
}

function vValidateInteger(Control)
{
	if(Control.value.indexOf(".") > -1)
	{
		vMarkErrorControl(Control, vMESSAGE_NON_DIGITAL);
		return false;
	}
	return vValidateDecimal(Control);
}
function vValidateDecimal(Control)
{

	var vMaxValue = GetAttribute(Control, "vMaxValue");
	var vMinValue = GetAttribute(Control, "vMinValue");
	//Validate control's configuration
	if(vMaxValue == null)
		vMaxValue = String(Number.MAX_VALUE);
	if(isNaN(vMaxValue))
		throw "\"" + Control.vMaxValue + "\" is not valid value for vMaxValue attribute.";
	if(vMinValue == null)
		vMinValue = String(-Number.MAX_VALUE);
	if(isNaN(vMinValue))
		throw "\"" + vMinValue + "\" is not valid value for vMinValue attribute.";
	if (Number(vMinValue) > Number(vMaxValue))
		throw "Value of attribute vMinValue cannot exceed value of attribute vMaxValue.";
	//Validate User's input
	if(!vValidateNonEmpty(Control))
		return false;
	if(isNaN(Control.value))
	{
		vMarkErrorControl(Control, vMESSAGE_NON_DIGITAL);	
		return false;
	}
	if(Number(Control.value) < Number(vMinValue))
	{
		vMarkErrorControl(Control, vMESSAGE_CANNOT_BE_LESS.replace("{0}", vMinValue));
		return false;
	}
	if(Number(Control.value) > Number(vMaxValue))
	{
		vMarkErrorControl(Control, vMESSAGE_CANNOT_EXCEED.replace("{0}", vMaxValue));
		return false;
	}
	vMarkSucsessControl(Control);
	return true;
}
function vValidateRegEx(Control)
{
	var vPattern = GetAttribute(Control, "vPattern");
	var vMessage = GetAttribute(Control, "vMessage");
	var expr;
	//Validate control's configuration
	if(vPattern == null)
		throw "vPattern attribute is required for RegEx check parameter."
	try
	{
		expr = new RegExp(vPattern);
	}
	catch(e)
	{
		if (e.name == "RegExpError")
			throw "\"" + vPattern + "\" is incorrect regular expression.\r\n\r\nSource Error: " + e.message
	}
	if(vMessage == null)
		throw "vMessage attribute is required for RegEx check parameter."
	
	var vRequired = GetAttribute(Control, "vRequired");
	if (vRequired == null)
		vRequired = "true";
	if (vRequired != "true" && vRequired != "false") 
		throw "Incorrect usage of vRequired attribute. The value must be bulean.\r\nCurrent value: " + vRequired;
	if(vRequired == "true")
	{
		if(!vValidateNonEmpty(Control))
			return false;
	}
	else if(Control.value == "")
	{
		vMarkSucsessControl(Control);
		return true;
	}
	
	//Validate User's input
	if(!vValidateTags(Control))
		return false;
	if(!expr.test(Control.value))
	{
		vMarkErrorControl(Control, vMessage);
		return false
	}
	vMarkSucsessControl(Control);
	return true;
}
function vValidateDate(Control) {
	vTrimIfRequired(Control);
	
	var vRequired = GetAttribute(Control, "vRequired");
	if (vRequired == null)
		vRequired = "true";
	if (vRequired != "true" && vRequired != "false") 
		throw "Incorrect usage of vRequired attribute. The value must be bulean.\r\nCurrent value: " + vRequired;
	if(vRequired == "true")
	{
		if(!vValidateNonEmpty(Control))
			return false;
	}
	else if(Control.value == "")
	{
		vMarkSucsessControl(Control);
		return true;
	}
	
	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{2}|\d{4})$/;
	var matchArray = Control.value.match(datePat);
	if (matchArray == null) {
		vMarkErrorControl(Control, vMESSAGE_INVALID_DATE_FORMAT);
		return false;
	}
	month = matchArray[1];
	day = matchArray[3];
	year = matchArray[4];
	if (month < 1 || month > 12)	
	{
		vMarkErrorControl(Control, vMESSAGE_INVALID_MONTH_NUMBER);
		return false;
	}
	if (day < 1 || day > 31)	
	{
		vMarkErrorControl(Control, vMESSAGE_INVALID_DAY_NUMBER);
		return false;
	}
	if ((month==4 || month==6 || month==9 || month==11) && day==31)	
	{
		vMarkErrorControl(Control, vMESSAGE_INVALID_DAY_NUMBER_NO31.replace("{0}", month));
		return false;
	}
	if (month == 2)	
	{
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day>29 || (day==29 && !isleap))	
		{
			vMarkErrorControl(Control, vMESSAGE_INVALID_MONTH_FEBRUARY.replace("{0}", year).replace("{1}", day));
			return false;
		}
	}
	vMarkSucsessControl(Control);
	return true;
}

function vValidateEmail(Control)
{
	vTrimIfRequired(Control);
	
	var vRequired = GetAttribute(Control, "vRequired");
	if (vRequired == null)
		vRequired = "true";
	if (vRequired != "true" && vRequired != "false") 
		throw "Incorrect usage of vRequired attribute. The value must be bulean.\r\nCurrent value: " + vRequired;
	if(vRequired == "true")
	{
		if(!vValidateNonEmpty(Control))
			return false;
	}
	else if(Control.value == "")
	{
		vMarkSucsessControl(Control);
		return true;
	}
	
	if(Control.value.search(/^[a-z\d_\-]([a-z\d_\-\.]*[a-z\d_\-])?@([a-z\d]([a-z\d\-]*[a-z\d])?\.)+[a-z]{2,4}$/i)<0)
	{
		vMarkErrorControl(Control, vMESSAGE_INVALID_EMAIL);
		return false;
	}
	vMarkSucsessControl(Control);	
	return true;
}

function vValidatePhone(Control)
{
	var vName = GetAttribute(Control, "vName");
	if (vName == null || vName == "")
	{
		throw "Incorrect usage of vName attribute. The value must be string.\r\nCurrent value: " + vName;
		return false;
	}
		
	vTrimIfRequired(Control);
	
	var vRequired = GetAttribute(Control, "vRequired");
	if (vRequired == null)
		vRequired = "true";
	if (vRequired != "true" && vRequired != "false") 
		throw "Incorrect usage of vRequired attribute. The value must be boolean.\r\nCurrent value: " + vRequired;
	if(vRequired == "true")
	{
		if(!vValidateNonEmpty(Control))
			return false;
	}
	else if(Control.value == "")
	{
		vMarkSucsessControl(Control);
		return true;
	}
	
	if(Control.value.search(/^\(\d{3}\) ?\d{3}\-\d{4}$/)<0)
	{
		vMarkErrorControl(Control, vMESSAGE_INVALID_PHONE.replace("{0}", vName));
		return false;
	}
	vMarkSucsessControl(Control);	
	return true;
}

function vTrimIfRequired(Control)
{
	var vTrim = GetAttribute(Control, "vTrim");
	if (vTrim == null)
		vTrim = "true";
	if (vTrim != "true" && vTrim != "false") 
		throw "Incorrect usage of vTrim attribute. The value must be bulean.\r\nCurrent value: " + vTrim;
	if (vTrim == "true")
	{
		Control.value = Trim(Control.value);	
	}
}

function vMarkErrorControl(Control, ToolTip)
{
	Control.style.backgroundColor = "yellow";
	Control.title = ToolTip;
}

function vMarkSucsessControl(Control)
{
	Control.style.backgroundColor = "white";
	Control.title = "";
}

function vRaiseClientError(Message)
{
	alert("Incorrect usage of validator.js module:\r\n" + Message);
	throw Message;
}


