function Form(formID) {
	this.formID = formID;
	this.fields = {};
	this.onValidate = this.defaultOnValidate;
	this._formElement = null;
}
Form.prototype.registerElement = function(name, title, type, params) {
	this.fields[name] = new FormField(this, name, title, type, params);
	return this.fields[name];
};
Form.prototype.validate = function() {
	var badField = null;
	this.onValidate.before && this.onValidate.before(this);
	for (var name in this.fields) {
		var field = this.fields[name];
		if (field.constructor != FormField) {
			alert(name);
		}
		var message = field.validate();
		if (message && !badField) {
			badField = field;
		}
		if (this.onValidate.field && this.onValidate.field(this, field, message)) {
			break;
		}
	}
	this.onValidate.after && this.onValidate.after(this, badField);
	if (badField) {
		badField.setFocus();
	}
	return (badField == null);
};
Form.prototype.validateField = function(name) {
	var field = this.fields[name];
	return this.onValidate.change && this.onValidate.change(this, field, field.validate());
};
// the function is used to init field with server-side validation message
Form.prototype.initErrorField = function(field, message) {
	field.value = field.getValue();
	field.message = message;
	this.onValidate.init && this.onValidate.init(this, field, message);
};
Form.prototype.getFormElement = function() {
	if (this._formElement == null) {
		this._formElement = document.getElementById(this.formID);
	}
	return this._formElement;
};
Form.prototype.defaultOnValidate = {
	alertTitle: "Next issues should be fixed before submit:\n",
	messagePrefix: "\n* ",
	_messages: "",
	before: function(form) {
		this._messages = "";
	},
	field: function(form, field, message) {
		if (message) {
			this._messages += this.messagePrefix + message;
		}
	},
	after: function(form, badField) {
		if (this._messages.length > 0) {
			alert(this.alertTitle + this._messages);
		}
	},
	init: function(form, field, message) {
		if (message) {
			alert(message);
		}
	}
};

function FormField(form, name, title, type, params) {
	this.form = form;
	this.name = name;
	this.title = title;
	this.type = type;
	this.getValue = this.defaultGetValueFunc;
	this.setValue = this.defaultSetValueFunc;
	this.setFocus = this.defaultSetFocusFunc;
	this.validate = this.defaultValidateFunc;
	this.params = params;
	if (typeof(params) == "string") {
		alert(params);
		this.params = {};
		params = params.split(",");
		for (var i = 0; i < params.length; i++) {
			var param = params[i].split("=");
			this.params[param[0]] = param[1] ? param[1] : true;
		}
	}
}
FormField.prototype.defaultGetValueFunc = function() {
	var v = null;
	var f = this.form.getFormElement().elements[this.name];
	if (f.type) {
		v = f.value;
	} else if (f.length) {
		for (var i = 0; i < f.length; i++) {
		  if (f[i].checked) {
		    v = f[i].value;
		    break;
		  }
		}
	}
	if (v && !this.params.dontTrim) {
		v = StringUtils.trim(v);
	}
	return v;
};
FormField.prototype.defaultSetValueFunc = function(value) {
	var f = this.form.getFormElement().elements[this.name];
	if (f.type) {
		f.value = value;
	} else if (f.length) {
		for (var i = 0; i < f.length; i++) {
			f[i].checked = (f[i].value == value);
		}
	}
};
FormField.prototype.defaultSetFocusFunc = function() {
	var f = this.form.getFormElement().elements[this.name];
	if (f.type) {
		f.focus();
	} else if (f.length) {
		f[0].focus();
	}
};
FormField.prototype.defaultValidateFunc = function() {
	this.value = this.getValue();
	this.formattedValue = this.value;
	this.message = ValidatorFactory.validate(this, this.type, this.params);
	if (!this.params.dontFormatValue) {
		this.setValue(this.formattedValue);
	}
	return this.message;
};
