var CGI_FormValidation = {
	Form: null, 
	Errors: [], 
	ShowErrors: true, 
	Error_Title: "An error has occured.",
	ErrorTypes:
	{
		Default: "", 
		Web: "The web address you supplied in <<field_name>> is invalid.",
		Email: "The email address you supplied in <<field_name>> is invalid.",
		Date: "The date you suppplied in <<field_name>> is invalid.", 
		CreditCard : "Please enter a valid credit card number in <<field_name>>.",
		Number: "The value you entered in <<field_name>> is not a number.",
		Checkbox: "Please select at-least one value for <<field_name>>.",
		Select: "Please select a value for <<field_name>>.",
		Radio: "Please select a value for <<field_name>>.",
		TooLong: "The text you entered is in <<field_name>> too long, the maximum allowed characters is <<max_length>>.",
		TooShort: "The text you entered in <<field_name>> is too short, the minimum allowed characters is <<min_length>>."
	}
};
if (typeof(Co_Translations))
	Co_Translations = {};

CGI_FormValidation.Validate = function(obj_or_name, onValidCallback, options)
{
	if (typeof(obj_or_name) == "string")
		this.Form = document.forms[obj_or_name];
	else
		this.Form = obj_or_name;
	this.Errors = [];
	if (typeof(options) != "object")
		options = {};
	
	if (typeof(this.Form.button_clicked) != "undefined")
	{
		if (this.Form.button_clicked == 2)
		{
			return true;
		}
	}
	
	var required, optional = false, field, first_invalid_field, is_valid = false, data_type, current_error;
	var group = options.group || "";
	var mark_as_submitted = ((typeof(options.mark_as_submitted) == "undefined" || options.mark_as_submitted == null) ? true : options.mark_as_submitted);
	
	if (typeof(this.Form.Submitted) != "undefined")
	{
		if (this.Form.Submitted)
		{
			return false;
		}
	}
	
	for (var i = 0; i < this.Form.length; i++)
	{
		field = this.Form[i];
		if (field.disabled)
			continue;
		
		if (group != "" && (field.getAttribute("group") || "") != group)
			continue;
		
		is_valid = false;
			
    required = field.getAttribute('required');
		optional = false;
		
		data_type = field.getAttribute("data_type") || "";
		
		if (required == null) required = false;
		switch (required.toString())
		{
			case "false" :
				required = false;
			break;
			case "optional" :
				required = false;
				optional = true;
			break;
			default:
				if (data_type == "" && typeof(required) == "string")
					data_type = required;
				required = true;
			break;
		}
		
		current_error = this.ErrorTypes.Default;
		switch (data_type.toLowerCase())
		{
			case "web" : case "link" : case "url" :
				if (this.IsUri(field.value) || (!required && field.value == ""))
					is_valid = this.ValidateFieldCondition(field);
				if (!is_valid)
					current_error = this.ErrorTypes.Web;
				break;
			case "email" :
				if (this.IsEmail(field.value) || (!required && field.value == ""))
					is_valid = this.ValidateFieldCondition(field);
				if (!is_valid)
					current_error = this.ErrorTypes.Email;
				break;
			case "date" :
				if (this.IsDate(field.value, field.getAttribute("date_delimiter")) || (!required && field.value == ""))
					is_valid = this.ValidateFieldCondition(field);
				if (!is_valid)
					current_error = this.ErrorTypes.Date;
				break;
			case "number" : case "int" :
				/* for some reason it seems that isNaN returns false if value is blank */
				if ((!isNaN(field.value.replace(/,/gi, "")) && field.value != "") || (!required && field.value == ""))
					is_valid = this.ValidateFieldCondition(field);
				if (!is_valid)
					current_error = this.ErrorTypes.Number;
				break;
			case "credit_card" : case "creditcard" :
				if (this.IsCreditCard(field.value) || (!required && field.value == ""))
					is_valid = this.ValidateFieldCondition(field);
				if (!is_valid)
					current_error = this.ErrorTypes.CreditCard;
				break;
			default :
				switch(required)
				{
					case false :
						if (!optional) continue;
					default:
						switch (field.type.toLowerCase()){
					    case 'hidden':
								if ((field.value != "" && field.getAttribute("vmessage") != "") || optional)
									is_valid = this.ValidateFieldCondition(field);
					    	break;
					    case 'radio':
								if ((this.GetSelectedIndex(this.Form[field.name]) >= 0) || optional)
									is_valid = this.ValidateFieldCondition(field);
								if (!is_valid)
									current_error = this.ErrorTypes.Radio;
					    	break;
							case 'checkbox' :
								if ((this.GetSelectedIndex(this.Form[field.name]) >= 0) || optional)
									is_valid = this.ValidateFieldCondition(field);
								if (!is_valid)
									current_error = this.ErrorTypes.Checkbox;
								break;
					    case 'select-one': case 'select' :
								if ((field.selectedIndex > 0) || optional)
									is_valid = this.ValidateFieldCondition(field);
								if ((field.selectedIndex == 0 && field[0].value != "") || optional)
									is_valid = this.ValidateFieldCondition(field);
								if (!is_valid)
									current_error = this.ErrorTypes.Select;
							break;
					    default:
								max_length = field.getAttribute("max_length")||-1;
								min_length = field.getAttribute("min_length")||-1;
								try
								{
									min_length = parseInt(min_length);
								}
								catch (e)
								{
									if (isNaN(min_length))
										min_length = -1;
								};
								try
								{
									max_length = parseInt(max_length);
								}
								catch (e)
								{
									if (isNaN(max_length))
										max_length = -1;
								};
								
								if (min_length > max_length && max_length > -1) min_length = -1;

								if ((field.value != "" || (max_length == 0 && field.value == "")) || optional)
								{
									is_valid = this.ValidateFieldCondition(field);
									if (min_length > 0 && is_valid)
									{
										if (field.value.length < min_length)
										{
											is_valid = false;
											current_error = this.ErrorTypes.TooShort;
										}
									}
									if (max_length > -1 && is_valid)
									{
										if (field.value.length > max_length)
										{
											is_valid = false;
											current_error = this.ErrorTypes.TooLong;
										}
									}
								}
									
							break;
				  	}
					break;
				}
			break;
		}
		if (!is_valid)
		{
			first_invalid_field = first_invalid_field || field;
			this.Errors.push({Message:this.GetFieldMessage(field, current_error), Field:field});
		}
	}
	if (this.Errors.length > 0)
	{
		if (this.ShowErrors)
		{
			if (typeof(Alert) == "function")
				Alert(this.GetError(), {title:this.Error_Title});
			else
				alert(this.GetError());
		}
		try{first_invalid_field.focus();first_invalid_field.select();}catch(e){};
		return false;
	}
	
	if (typeof(onValidCallback) == "function")
	{
		var return_val = onValidCallback(this.Form);
		this.Form.Submitted = (return_val && mark_as_submitted);
		return return_val;
	}
	
	this.Form.Submitted = mark_as_submitted;
	return true; 
}
CGI_FormValidation.ValidateFieldCondition = function(fld)
{
	if (!fld.getAttribute("condition")) return true;
	fld.Validate = function()
	{
		return eval(this.getAttribute("condition"));
	}
	return fld.Validate();
}
CGI_FormValidation.GetSelectedIndex=function(obj_or_name)
{
	var obj;
	if (typeof(obj_or_name)=="string") obj = document.getElementById(obj_or_name); else obj = obj_or_name;
	if (typeof(obj.length)=="undefined")
	{
		if (obj.checked)
			return 0;
		return -1;
	};
	var i,ol;
	for (i=0,ol=obj.length;i<ol;i++)
		if(obj[i].checked) return i;
		
	return -1;
}
CGI_FormValidation.GetSelectedItem=function(obj_or_name)
{
	var idx = this.GetSelectedIndex(obj_or_name);
	
	if (idx == -1) return null;
	
	var obj;
	if (typeof(obj_or_name)=="string") obj = document.getElementById(obj_or_name); else obj = obj_or_name;
	
	if (typeof(obj.length)=="undefined")
		return obj;
		
	return obj[idx];
}
CGI_FormValidation.IsUri = function(s_val)
{
	return s_val.match(/^(?:http(?:s?)\:\/\/|~\/|\/)?(?:(?:[-\w]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2,4}))(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$/gi) != null;
}
CGI_FormValidation.IsEmail = function(s_val)
{
//	/(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})/gi
//	/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/gi

	return s_val.match(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/gi) != null;
/*
	var invalidChars="`~!#$%^&*()+|<>?/:,; ";

	for(i = 0; i < invalidChars.length; i++)
	{
		var badChar = invalidChars.charAt(i);
		if(s_val.indexOf(badChar, 0) != -1)
			return false;
	}
	var atPos = s_val.indexOf("@", 1)
	if(atPos == -1) return false;
	if(s_val.indexOf("@", atPos + 1) != -1) return false;

	var periodPos = s_val.indexOf(".", atPos)
	if(periodPos == -1) return false;
	if(periodPos + 3 > s_val.length) return false;
	return true;
*/
}
CGI_FormValidation.IsDate = function(s_val, delimiter)
{
	if (typeof(delimiter) == "undefined" || delimiter == null || delimiter == "")
		delimiter = "./-";
	var re = new RegExp("^\\s*?([0]?[1-9]|[1][0-2])[" + delimiter + "]([0]?[1-9]|[1|2][0-9]|[3][0|1])[" + delimiter + "]([0-9]{4}|[0-9]{2})\\s*?$", "gi");
	return re.test(s_val);
}
CGI_FormValidation.IsCreditCard = function(s_val)
{
	s_val = s_val.replace(/[\s\-]/gi, "");
	return s_val.match(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/g) != null;
}
CGI_FormValidation.GetFieldMessage = function(field, current_error)
{
	var custom_message = field.getAttribute("vmessage")||"";
	var max_length = field.getAttribute("max_length")||-1;
	var min_length = field.getAttribute("min_length")||-1;
	var field_value = field.value;
	var field_name;
	if(field.getAttribute('display_name'))
	{
		field_name = field.getAttribute('display_name');
	}
	else
	{
		if (field.id)
		{
			field_name = field.id;
		}
		else
		{
			field_name = field.name;
		}
	}
	if (custom_message != "" && custom_message.indexOf(' ')!=-1)
		current_error = custom_message;
		
	if (current_error == this.ErrorTypes.Default)
	{
		current_error = "Please enter a value in <<field_name>>.";
	}
	
	current_error = current_error.replace(/<<field_name>>/gi, field_name);
	current_error = current_error.replace(/<<field_value>>/gi, field_value);
	current_error = current_error.replace(/<<max_length>>/gi, max_length);
	current_error = current_error.replace(/<<min_length>>/gi, min_length);
	
	var matches = current_error.match(/<<[^>]*>>/g);
	if (matches != null)
	{
		for (var i = 0; i < matches.length; i++)
		{
			current_error = current_error.replace(matches[i], field.getAttribute(matches[i].replace(/[<>]/g, "")));
		}
	}
	
	return current_error;
}
CGI_FormValidation.GetError = function()
{
	if (this.Errors.length == 0)
		return "";
	var return_message = "The following errors occured:\r\n";
	for (var i = 0; i < this.Errors.length; i++)
	{
		return_message += "\r\n - " + this.Errors[i].Message;
	}
	return_message += "\r\n\r\nPlease correct these errors and try again.";
	return return_message;
}