(function() {
// shorthand aliases
var L = YAHOO.lang, _GT = ZC.Util.GetText, sprintf = ZC.Util.sprintf;
// reused to hold new validator class, to cut down the amount of repetition, and to aid with minifying the file
var oValidator;

oValidator = ZC.Core.Validator.Create("AlphaNumericNoSpace");
oValidator.prototype.sDefaultValidationMessage = _GT("Only A-Z a-z 0-9 _ and - are valid (no spaces)");
oValidator.prototype.oValidationRegex = /^([A-Za-z0-9_-])*$/;

oValidator = ZC.Core.Validator.Create("AlphaNumericSpace");
oValidator.prototype.sDefaultValidationMessage = _GT("Only A-Z a-z 0-9 _ - and spaces are valid");
oValidator.prototype.oValidationRegex = /^([A-Za-z0-9_ -])*$/;

oValidator = ZC.Core.Validator.Create("ArrayElementCount");
oValidator.prototype.sDefaultValidationMessage = _GT("Please select the appropriate number of elements.");
oValidator.prototype.Validate = function (Value, oWidget)
{
	var iMin = oWidget.aDef.MinArrayElements || 0;
	var iMax = oWidget.aDef.MaxArrayElements || 0;
	var iCount;
	
	if (L.isArray(Value))
	{
		iCount = Value.length;
	}
	else if (L.isString(Value) && Value.length)
	{
		iCount = 1;
	}
	else
	{
		iCount = 0; 	// zero length string
	}
	
	if (iCount == 0) return true;
	
	return (!((iMin && iCount < iMin) || (iMax && iCount > iMax)));
}

oValidator = ZC.Core.Validator.Create("CompareTo");
oValidator.prototype.sDefaultValidationMessage = _GT("The selection in this field must be greater than the value of the other field.");
oValidator.prototype.Validate = function(Value, oWidget)
{
	if (L.isUndefined(oWidget.aDef.GreaterThanField) && L.isUndefined(oWidget.aDef.LessThanField))
		return true;

	var aMessages = [];
	var bValid = true;
	if (oWidget.aDef.GreaterThanField)
	{
		var aWidgets = oWidget.aDef.GreaterThanField;
		if (L.isString(aWidgets))
			aWidgets = [aWidgets];

		ZC.Util.ForEach(aWidgets, function(sGreaterThanWidgetName)
		{
			var oGreaterThanWidget = ZC.JSManager.GetWidget(sGreaterThanWidgetName);

			bValid = bValid && (Value > oGreaterThanWidget.GetValue());
			aMessages.push(sprintf(_GT("greater than the value in %s"), oGreaterThanWidget.GetCaption()));
		});
	}

	if (oWidget.aDef.LessThanField)
	{
		var aWidgets = oWidget.aDef.LessThanField;
		if (L.isString(aWidgets))
			aWidgets = [aWidgets];

		ZC.Util.ForEach(aWidgets, function(sLessThanWidgetName)
		{
			var oLessThanWidget = ZC.JSManager.GetWidget(sLessThanWidgetName);

			bValid = bValid && (Value < oLessThanWidget.GetValue());
			aMessages.push(sprintf(_GT("less than the value in %s"), oGreaterThanWidget.GetCaption()));
		});
	}

	this.sDefaultValidationMessage = sprintf(_GT("The selection must be %s"), aMessages.join(_GT(" and ")));
	return bValid;
}

oValidator = ZC.Core.Validator.Create("DomainName");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a valid domain name; e.g. www.google.com:%");
oValidator.prototype.oValidationRegex = /^[0-9a-zA-Z._-]*$/;

var sDisplayNameRegex = "[a-zA-Z\\d!#$%&'*+\\\\/=?^_`{|}~\\s-]+";	
var sAddressRegex = "['A-Za-z0-9_.-]+@(['A-Za-z0-9_-]+\\.['A-Za-z0-9_.-]+)";
var sEmailRegex = "((" + sDisplayNameRegex + ")?\\s*<" + sAddressRegex + ">|" + sAddressRegex + ")?";

oValidator = ZC.Core.Validator.Create("EmailAddress");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a valid e-mail address");
oValidator.prototype.oValidationRegex = new RegExp("^" + sEmailRegex + "$");

oValidator = ZC.Core.Validator.Create("EmailAddresses");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a valid e-mail address[es] (separated with commas)");
oValidator.prototype.oValidationRegex = new RegExp("^(" + sEmailRegex + "\\s*,\\s*)*" + sEmailRegex + "$", "m");

oValidator = ZC.Core.Validator.Create("EmailAddressesNewLineSeperated");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a valid e-mail address[es] (one per line)");
oValidator.prototype.oValidationRegex = new RegExp("^(" + sEmailRegex + "\\s*\\n\\s*)*" + sEmailRegex + "$", "m");

oValidator = ZC.Core.Validator.Create("HTMLColour");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a valid HTML colour");
oValidator.prototype.oValidationRegex = /^(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow|#[0-9A-F]{6})$/i;

oValidator = ZC.Core.Validator.Create("Hex6Digits");
oValidator.prototype.sDefaultValidationMessage = _GT("Please ensure the data is of the format ff00aa (6 digits from 0-9 plus a,b,c,d,e and f)");
oValidator.prototype.oValidationRegex = /^[0-9A-F]{6}$/i;

oValidator = ZC.Core.Validator.Create("HexHTMLColour");
oValidator.prototype.sDefaultValidationMessage = _GT("Please ensure the data is of the format #ff00aa (a hash followed by 6 digits from 0-9 plus a,b,c,d,e and f)");
oValidator.prototype.oValidationRegex = /^#[0-9A-F]{6}$/i;

oValidator = ZC.Core.Validator.Create("HexHTMLColour");
oValidator.prototype.sDefaultValidationMessage = _GT("Please ensure the data is of the format #ff00aa (a hash followed by 6 digits from 0-9 plus a,b,c,d,e and f)");
oValidator.prototype.oValidationRegex = /^#[0-9A-F]{6}$/i;

oValidator = ZC.Core.Validator.Create("IsFutureDate");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a date in the future.");
oValidator.prototype.Validate = function(Value, oWidget)
{
	if (!Value) return true;

	var oToday = new Date();
	if(oWidget.aDef.AllowToday)
	{
		oToday.setHours(0);
		oToday.setMinutes(0);
		oToday.setSeconds(0);
	}
	else
	{
		oToday.setHours(23);
		oToday.setMinutes(59);
		oToday.setSeconds(59);
	}

	return Value > oToday;
}

oValidator = ZC.Core.Validator.Create("IsHumanAge");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a whole number less than 100.");
oValidator.prototype.oValidationRegex = /^\d{0,2}$/;

oValidator = ZC.Core.Validator.Create("IsInteger");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a whole number.");
oValidator.prototype.oValidationRegex = /^-?\d*$/;

oValidator = ZC.Core.Validator.Create("IsNaturalNumber");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a whole number greater than zero.");
oValidator.prototype.oValidationRegex = /^(\d*[1-9]\d*)*$/;

oValidator = ZC.Core.Validator.Create("IsNonNegativeInteger");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a whole non-negative number.");
oValidator.prototype.oValidationRegex = /^\d*$/;

oValidator = ZC.Core.Validator.Create("IsPositive");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a positive number.");
oValidator.prototype.oValidationRegex = /^\d*([,.]\d+)?$/;

oValidator = ZC.Core.Validator.Create("IsYear");
oValidator.prototype.sDefaultValidationMessage = _GT("Please enter a 4 digit year.");
oValidator.prototype.Validate = function(Value, oWidget)
{
	if(Value == '')
		return true;

	var bValid = Value.match(/^\d{4}$/);
	var iMaxYear = oWidget.aDef.MaxYear;
	var iMinYear = oWidget.aDef.MinYear;
	if (iMinYear && iMaxYear)
	{
		this.sDefaultValidationMessage = sprintf(_GT('Please enter a 4 digit year between %d and %d.'), iMinYear, iMaxYear);
		bValid = bValid && (Value >= iMinYear && Value <= iMaxYear);
	}
	else if (iMaxYear)
	{
		this.sDefaultValidationMessage = sprintf(_GT('Please enter a 4 digit year before %d.'), iMaxYear);
		bValid = bValid && (Value <= iMaxYear);

	}
	else if (iMinYear)
	{
		this.sDefaultValidationMessage = sprintf(_GT('Please enter a 4 digit year after %d.'), iMinYear);
		bValid = bValid && (Value >= iMinYear);
	}

	return bValid;
}

oValidator = ZC.Core.Validator.Create("MassMail_AutomaticRecipients");
oValidator.prototype.sDefaultValidationMessage = _GT('The option you have selected is invalid');
oValidator.prototype.Validate = function (Value, oWidget)
{
	var oMaxRecipientsWidget = oWidget.oForm.GetWidget('MaxRecipients');
	var oRoleWidget = oWidget.oForm.GetWidget('Role');
	var oPresetEmailsWidget = oWidget.oForm.GetWidget('PresetEmailAddresses');
	
	switch(Value)
	{
		case 1:
			if (oMaxRecipientsWidget.GetValue() == -1)
			{
				this.sDefaultValidationMessage = _GT('This option is not valid when there are no manual recipients');
				return false;
			}	
			break;
				
		case 2:
			if (oRoleWidget.GetValue() == '')
			{
				oRoleWidget.SetValid(false, _GT('You must specify a role'));
				this.sDefaultValidationMessage = _GT('You must specify a role below');
				return false;
			}	
			break;
		case 3:			
			if (oPresetEmailsWidget.GetValue() == '')
			{
				oMaxRecipientsWidget.SetValid(false, _GT('You must specify at least one email address'));
				this.sDefaultValidationMessage = _GT('You must specify at least one preset email address below');
				return false;
			}	
			break;
	}		
	return true;
}

oValidator = ZC.Core.Validator.Create("MaxDecimalPlaces");
oValidator.prototype.Validate = function (Value, oWidget)
{
	this.sDefaultValidationMessage = sprintf(_GT('Please specify this value using no more than %d decimal places.'), oWidget.aDef.MaxDP);
	
	var oDPRegex = new RegExp("^\\d*([,.]\\d{1," + oWidget.aDef.MaxDP + "})?$");
	return oDPRegex.test(Value);
}

oValidator = ZC.Core.Validator.Create("MaxLength");
oValidator.prototype.Validate = function (Value, oWidget)
{
	var iMaxLength = oWidget.aDef.MaxLength;
	this.sDefaultValidationMessage = sprintf(_GT('Please reduce this to %d  characters, it is currently at %d.'), iMaxLength, Value.length);
	
	return (Value.length < iMaxLength);
}

oValidator = ZC.Core.Validator.Create("NotBlank");
oValidator.prototype.sDefaultValidationMessage = _GT("Please complete this.");
oValidator.prototype.Validate = function (Value, oWidget)
{
	return (Value.length > 0);
}

oValidator = ZC.Core.Validator.Create("PositiveCurrency");
oValidator.prototype.sDefaultValidationMessage = _GT('Please enter a number with no more than two decimal places.');
oValidator.prototype.oValidationRegex = /^\d*([.,]\d{1,2})?$/;

oValidator = ZC.Core.Validator.Create("Regex_Multiline");
oValidator.prototype.sDefaultValidationMessage = _GT("One or more lines are in an invalid format");
oValidator.prototype.Validate = function (Value, oWidget)
{
	var sRegex = oWidget.aDef.Validator_Regex_Multiline;
	if (!sRegex)
		return true;
	var oRegex = new RegExp(sRegex);

	var aLines = Value.split(/\n/);
	return !ZC.Util.Some(aLines, function(sLine)
	{
		sLine = sLine.replace(/(^\s*|\s$)/g, '');
		return (sLine.length && !oRegex.test(sLine));
	});
}

var sSMSNumberRegexp = "[1-9]\\d{8,15}";
oValidator = ZC.Core.Validator.Create("SMSNumber");
oValidator.prototype.sDefaultValidationMessage = _GT('Please enter a valid international number including the country code.  UK mobile numbers start with 44 and omit the first 0.');
oValidator.prototype.oValidationRegex = new RegExp('^' + sSMSNumberRegexp + '$');

oValidator = ZC.Core.Validator.Create("SMSNumbers");
oValidator.prototype.sDefaultValidationMessage = _GT('Please enter valid international numbers including the country code, separated by commas or newlines.');
oValidator.prototype.oValidationRegex = new RegExp('^' + sSMSNumberRegexp + "([,\\n]" + sSMSNumberRegexp + ")*$");

oValidator = ZC.Core.Validator.Create("SelectMinMax");
oValidator.prototype.sDefaultValidationMessage = _GT('You must select at least 1 and no more than 3 counties');
oValidator.prototype.Validate = function (Value, oWidget)
{
	if (Value instanceof Array)
	{
		var iMin = oWidget.aDef.SelectMin || 0;
		var iMax = oWidget.aDef.SelectMax || 0;
		
		if (iMax > 0)
			this.sDefaultValidationMessage = sprintf(_GT("You must select at least %d and no more than %d."), iMin, iMax);
		else
			this.sDefaultValidationMessage = sprintf(_GT("You must select at least %d."), iMin);
	
		if (Value.length >= iMin && (iMax == 0 || Value.length <= iMax))
			return true;
	}
	return false;	
}

oValidator = ZC.Core.Validator.Create("TelephoneNumber");
oValidator.prototype.sDefaultValidationMessage = _GT('Please enter a valid telephone number excluding the country code.');
oValidator.prototype.oValidationRegex = /^[^a-zA-Z]*$/;

oValidator = ZC.Core.Validator.Create("TwoTokensValidator");
oValidator.prototype.sDefaultValidationMessage = _GT('A maximum of two words is allowed');
oValidator.prototype.oValidationRegex = /^(\S+( \S+)?)?$/;

oValidator = ZC.Core.Validator.Create("URL");
oValidator.prototype.sDefaultValidationMessage = _GT('Please enter a valid URL beginning http://');
oValidator.prototype.oValidationRegex = /^https?:\/\/\S+$/;

oValidator = ZC.Core.Validator.Create("WhiteSpaceSeparatedIntegers");
oValidator.prototype.sDefaultValidationMessage = _GT('Please enter one or more whole numbers separated by a space e.g. "1 2 3".');
oValidator.prototype.oValidationRegex = /^(\d+\s+)*$/;

})();
