/* Possible special rules:
 * min_chars => int
 * max_chars => int
 * type => [date, email, phone, number]
 * equal => equal_to_field_name
 * required => boolean
 * callback => function
 */
var form_validate = {
	errors : new Hash(),

	/* Patterns */
	date_pattern : /^([\d]{1,2})\/([\d]{1,2})\/(\d\d\d\d)$/i,
	mail_pattern : /^[^@]+@{1}[^\.]+\.{1}.*$/i,
	phone_pattern : /^([\d|\-]{6,})$/i,

	/* Checking functions */
	check_date : function(date)
	{
		return !!this.date_pattern.test(date);
	},

	check_email : function(email)
	{
		return !!this.mail_pattern.test(email);
	},

	check_equal : function(str1, str2)
	{
		return (str1 == str2);
	},

	check_min_chars : function(str, min)
	{
		return str.length >= parseInt(min);
	},

	check_max_chars : function(str, max)
	{
		return str.length <= parseInt(max);
	},

	check_phone : function(phone)
	{
		return !!this.phone_pattern.test(phone);
	},

	/* Aliases */
	empty : function(str)
	{
		return ( str == null || str == "" );
	},

	exists : function(name, obj)
	{
		return ( $defined(obj) && $defined(obj[name]) );
	},

	in_string : function(str, needle)
	{
		return ( str.indexOf(needle) != -1 );
	},

	/* Main functions */
	add_error : function(str, field_name)
	{
		this.errors[field_name] = str;
	},

	validate : function(form, special_fields)
	{
		if ( typeof special_fields == "undefined" )
			special_fields = new Object();

		for (var i = 0; i < form.elements.length; i++) {
			var el = form.elements[i];

			if (this.in_string(el.name, "_req")) {
				if (this.in_string(el.name, "email"))
					if (!this.check_email(el.value))
						this.add_error("Wrong E-Mail", el.name);

				if (this.in_string(el.name, "date"))
					if (!this.check_date(el.value))
						this.add_error("Wrong Date", el.name);

				if (this.in_string(el.name, "phone"))
					if (!this.check_phone(el.value))
						this.add_error("Wrong phone number", el.name);

				if (this.empty(el.value))
					this.add_error("Required field is empty", el.name);
			}

			if (this.in_string(el.name, "_confirm")) {
				var name = el.name.replace("_confirm", "");

				if (this.exists(name, form)) {
					if (!this.check_equal(form[name].value, el.value))
						this.add_error("Wrong confirmation", el.name);
				}
			}

			if (this.exists(el.name, special_fields)) {
				var rules = special_fields[el.name];
				if (this.exists('min_chars', rules))
					if (!this.check_min_chars(el.value, rules['min_chars']))
						this.add_error("Not enough chars", el.name);

				if (this.exists('max_chars', rules))
					if (!this.check_max_chars(el.value, rules['max_chars']))
						this.add_error("Too many chars", el.name);

				if (this.exists('equal', rules))
					if (!this.check_equal(el.value, form[rules['equal']].value))
						this.add_error("Not equivalent to " + rules['equal'] + " field", el.name);

				if (this.exists('type', rules))
					if (rules['type'] == 'date')
						if (!this.check_date(el.value))
							this.add_error("Wrong Date", el.name);
						else
							if (rules['type'] == 'email')
								if (!this.check_email(el.value))
									this.add_error("Wrong E-Mail", el.name);
								else
									if (rules['type'] == 'phone')
										if (!this.check_phone(el.value))
											this.add_error("Wrong phone number", el.name);
										else
											if (rules['type'] == 'number')
												if (isNaN(el.value))
													this.add_error("Not a number", el.name);

				if (this.exists('required', rules) && !!rules['required'])
					if (this.empty(el.value))
						this.add_error("Required field is empty", el.name);

				if (this.exists('callback', rules))
					if (!rules['callback'](el.value))
						this.add_error("Error", el.name);
			}
		}

		if ( this.errors.getLength() > 0 )
		{
			var error_string = "";
			var errors = this.errors;
			for ( var j = 0; j<this.errors.length; j++ )
				error_string += this.errors[j]+"\n";

			//alert(error_string);
			this.errors = new Hash();

			return errors;
		}

		form.submit();
		return true;
	}
};