function Verify () {
	this.filters = new Array();
	this.suffix_message = '';
	this.valid = true;

	this.load = function () {
		$('form[@verify=true]').bind('submit', function () {
			return Verify.submit(this);
		});

		this.check_onlyifenforce_fields();

		$('input[@verify]:text').add('textarea[@verify]').bind('blur', function () {
			Verify.check_onlyifenforce_fields();
		});
		$('input[@verify]:radio').add('input[@verify]:checkbox').add('select[@verify]').bind('click', function () {
			Verify.check_onlyifenforce_fields();
		});
	}

	this.submit = function (form) {
		var error;
		var Verify = this;	

		// add custom filters
		if (typeof(filters) != 'undefined') {
			for (type in filters) {
				this.filters[type] = new Array();	
				this.filters[type]['message'] = filters[type]['message'];	
				this.filters[type]['regexp'] = filters[type]['regexp'];	
			}
		}

		var retval = true;
		$('input[@verify]', form).add('select[@verify]', form).add('textarea[@verify]', form).each(function () {
			if ((error = Verify.is_valid(this)) != true) {
				return retval=Verify.error(error, this);
			} else {
				$(this).removeClass('error');
			}
		});

		Verify.valid = retval;
		return retval;
	}

	this.is_valid = function (element) {
		var verify = $(element).attr('verify');
		var onlyif = $(element).attr('onlyif');
		var onlyifenforce = $(element).attr('onlyifenforce');
		var same_as = $(element).attr('sameas');

		var enforce = false;
		if (typeof(onlyifenforce) != 'undefined' && onlyifenforce.length > 0) {
			enforce = true;
			onlyif=onlyifenforce;
		}

		var cont = true;
		if (onlyif) {
			cont = this.check_only_if(element, onlyif, enforce);
		}
	
		if (verify && cont) { 
			var input_value = this.get_element_value(element);

			if (same_as) {
				var same = true;
				var field_desc;
				
				var same_element = this.get_element_by_name(element.form, same_as);
				var same_value = this.get_element_value(same_element);

				if (input_value!=same_value) {
					return 'not_same '+same_element.getAttribute('description');
				}
			}		
		
//			if (this.in_string('unique', verify) || this.in_string('unique_if_changed', verify)) {
			if (this.in_string('unique', verify) || this.in_string('unique_if_changed', verify) ||
				this.in_string('function', verify) || this.in_string('function_if_changed', verify)
			) {
				var cont = true;
				var if_changed = false;

				if (this.in_string('unique_if_changed', verify) || this.in_string('function_if_changed', verify)) {
					cont = false;
					if_changed = true;
	
					if (element.value != element.defaultValue || element.defaultValue.length==0) {
						cont = true;
					}
				}

				if (document.getElementsByTagName && cont) {
					var url = this.get_ajax_url(element, if_changed);
					var unique;

					$.ajax({
						async: false,
						dataType: "xml",
						type: "GET",
						url: url,
						success: function (data) {
							unique = data.getElementsByTagName('unique')[0].firstChild.data;
						}
					});

					if (unique == 0) {
						return 'unique';
					}
				}
			}

			for (type in this.filters) {
				if (typeof(this.filters[type]['regexp']) != 'undefined') {
					var regexp = new RegExp(this.filters[type]['regexp']);

					if (this.in_string(type, verify) || this.in_string('empty_or_'+type, verify)) {
						var empty_ok = false;
						if (this.in_string('empty_or_'+type, verify)) {
							empty_ok = true;
						}

						if ((!empty_ok && !regexp.test(input_value)) || (empty_ok && input_value.length!=0 && !regexp.test(input_value))) {
							return type;
						}
					}
				}
			}
		}
	
		return true;
	}

	this.error = function (error, element) {
		var Verify=this;

		var verify = element.getAttribute('verify');
		var desc = element.getAttribute('description');
		
		if (!desc || desc.length==0) {
			desc = element.name;
		}
	
		element.focus();
		$(element).not('[@type=radio][@type=checkbox]').addClass('error');
		$(element).bind('blur', function () {
			Verify.restore_background(this);
		});

		var desc_same;
		if (error.substr(0,8) == 'not_same') {
			desc_same = error.substr(9);		
			error = error.substr(0,8);
		}

		for (type in this.filters) {
			if (error==type) {
				var message = this.filters[type]['message'].replace(/\{\$desc\}/g, desc);

				if (typeof(desc_same) != 'undefined') {
					message = message.replace(/\{\$desc_same\}/, desc_same);
				}

				if (this.suffix_message.length > 0) {
					message += ' '+this.suffix_message;
				}

				if ($('div#verify_errors')[0]) {
					var div = $('div#verify_errors');
					
					if ($(div).text() != message) {
						$(div).stop().empty().hide().append('<ul><li><span>'+message+'</span></li></ul>').fadeIn('slow');
					}
				} else {
					alert(message);
				}
			}
		}
		
		return false;
	}

	/* supporting functions */
	
	/*
		call with element only if element = inputobject
		call with element name and formobject if element = string
	*/
	this.get_element_value = function (element, form) {
		if (typeof(element) == 'string' && typeof(form) != 'undefined') {
			element = this.get_element_by_name(element.form, element);
		}


		var value='';
		if (element.type == 'radio') {
			$(element.form).find('input[@name="'+element.name+'"]').each(function () {
				if ($(this).attr('checked')) value = $(this).val();
			});
		} else if (element.type == 'select-one') {
			$(element.form).find('select[@name="'+element.name+'"]').find('option[@selected]').each(function () {
				value = $(this).val();
			});
		} else if (element.type == 'select-multiple') {
			if ($(element).val() != null) value = $(element).val();
		} else if (element.type == 'text' || element.type == 'password' || (element.type == 'checkbox' && element.checked)) {
			value = element.value;
		} else if (element.type == 'textarea') {
			value = $(element).val();
		}
		
		return value;
	}

	this.get_element_by_name = function (form, field) {
		var element;
		$('input[@name='+field+']', form).add('select[@name='+field+']', form).each(function () {
			element=this;
		});
		return element;
	}

	this.restore_background = function (element) {
		if (this.is_valid(element)==true) {
			if ($('div#verify_errors')[0]) {
				var div = $('div#verify_errors');
				$(div).fadeOut('slow', function () {
					$(this).empty();
				});
			}

			$(element).removeClass('error');
		}
	}

	this.in_string = function (needle, haystack) {
		var parts = haystack.split(' ');
			
		for (var i=0;i<parts.length;i++) {
			if (parts[i] == needle) {
				return true;
			}
		}
	
		return false;
	}

	this.get_ajax_url = function (element, if_changed) {
		var parts = window.location.toString().split('?');
	
		var url = parts[0];
		var query = parts[1];
	
		var qs_add = '';
		if (query) {
			parts = query.split('&');
			for (i in parts) {
				var qs = parts[i].split('=');
				if (qs[0] == 'page') {
					qs_add += qs[0]+'='+qs[1]+'&';
				}
			}
		}
	
		url += '?'+qs_add+'vf_action=check_with_function';
		if (if_changed) url += '_if_changed';
		url += '&vf_field='+escape(element.name)+'&vf_value='+escape(element.value);
	
		return url;
	}

	/* check all 'only_if_enforce' fields for enabling/disabling */
	this.check_onlyifenforce_fields = function () {
		$('input[@onlyifenforce]').each(function () {
			if (!Verify.check_only_if($(this)[0], $(this).attr('onlyifenforce'), true)) {
				$(this).attr('disabled', true);
				$(this).addClass('disabled');
			}
		});
	}

	/* verify if 'only_if' conditions have been met */
	this.check_only_if = function (element, onlyif, enforce) {
		var cont = false;
		var pairs = onlyif.split('|');
		var matches = 0;

		for (i in pairs) {
			var parts = pairs[i].split('=', 2);
			
			var field = parts[0];
			var value = parts[1];

			var check_value = this.get_element_value(field, element.form);

			if (value.substr(0, 1) == '/' && value.substr(-1) == '/') {
				var regexp = new RegExp(value.substr(1, value.length-2));

				if (!regexp.test(check_value)) {
					matches++;
				}
			} else if (check_value == value) {
				matches++;
			}
		}

		if (matches==pairs.length) {
			cont = true;

			$(element).attr('disabled', false);
			$(element).removeClass('disabled');
		}
		
		return cont;
	}

	this.set_suffix_message = function (message) {
		this.suffix_message = message;
	}

	this.add_filter = function (name, message, regexp) {
		this.filters[name] = new Array();
		this.filters[name]['message'] = message;

		if (typeof(regexp) != 'undefined')
			this.filters[name]['regexp'] = regexp;
	}
}

/*$(document).ready(function(){
	Verify.load();
});*/

var Verify = new Verify();