/*  Validator, version 0.2.1
 *  (c) 2005 Kan Fushihara <kan.fushihara@gmail.com>
 *
 *  Validator is freely distributable under the terms of an MIT-style license.
 *
/*--------------------------------------------------------------------------*/

var Validator = Class.create();

Validator.Version = '0.2.1';

Validator.ErrorMessage    = {};
Validator.ParamName       = {};
Validator.FunctionMessage = {};

Validator.prototype = {
	initialize: function(form) {
		this.form       = $(form);
		this.elements   = Form.getElements(this.form);
		this.validators = {};
		this.n_color    = 'white';
		this.a_color    = '#ffa';

		for (var i=0; i<this.elements.length; i++) {
			new Form.Element.EventObserver(this.elements[i], this.listener.bindAsEventListener(this));
		}

		Event.observe(form, 'submit', this.submit.bindAsEventListener(this), true);
	},

	check: function() {
		var name      = arguments[0];

		if (!this.validators[name]) this.validators[name] = [];
		if (!this.validators[name].callbacks) this.validators[name].callbacks = [];
		for (var i=1; i < arguments.length; i++) {
			if(typeof arguments[i] == 'function')
				this.validators[name].callbacks.push(arguments[i]);
			else
				this.validators[name].push(arguments[i]);
		}
	},

	submit: function(event) {
		var checks   = 0;

		for (name in this.validators) {
			checks += this.valid(name);
		}

		if (checks > 0) Event.stop(event);
	},

	getFormValue: function(name) {
		var value    = new Array();

		for (var i = 0; i < this.elements.length; i++) {
			if (this.elements[i].name == name) {
				if ($F(this.elements[i])) value.push($F(this.elements[i]));
			}
		}
		if (value.length == 0) {
			return "";
		} else if (value.length == 1) {
			return value[0];
		} else {
			return value;
		}
	},

	getParamName: function(name) {
		if (Validator.ParamName[name]) {
			return Validator.ParamName[name];
		} else {
			return name;
		}
	},

	getFunctionMessage: function(name) {
		return Validator.FunctionMessage[name];
	},

	getErrorMessage: function(param, func) {
		var msg = Validator.ErrorMessage[param + '.' + func];
		if(!msg) msg = this.getParamName(param) + this.getFunctionMessage(func);

		return msg;
	},

	dispErrorMessage: function(name, message) {
		try{
			$('valid_' + this.form.id + '_' + name).innerHTML = message;
		}catch(e){}
	},

	colorChange: function(name, error) {
		for (var i = 0; i < this.elements.length; i++) {
			if (this.elements[i].name == name) {
				if (error == 0) {
					this.elements[i].style.backgroundColor = this.n_color;
				} else {
					this.elements[i].style.backgroundColor = this.a_color;
				}
			}
		}
	},

	listener: function(element, value) {
		this.valid(element.name);
	},

	valid: function(name) {
		var value     = this.getFormValue(name);
		var validator = this.validators[name];
		var errors    = 0;
		var error_msg = '';

		if (typeof(validator) != 'object') return 0;

		for (var i = 0; i < validator.length; i++) {
			if (!validator[i].check(value)) {
				for(var j = 0; j < validator.callbacks.length; j++) {
					validator.callbacks[j].call(this, name);
				}
				error_msg += this.getErrorMessage(name, validator[i].name);
				errors++;
			}
		}

		this.dispErrorMessage(name, error_msg);
		this.colorChange(name, errors);

		return errors;
	}
};
// default validator message
Validator.FunctionMessage['NOT_NULL']      = ' is null. ';
Validator.FunctionMessage['INT']           = ' is not integer. ';
Validator.FunctionMessage['UINT']          = ' is not unsigned integer. ';
Validator.FunctionMessage['REAL']          = ' is not real number. ';
Validator.FunctionMessage['UREAL']         = ' is not real number. ';
Validator.FunctionMessage['ASCII']         = ' is not ascii character. ';
Validator.FunctionMessage['LENGTH_UNDER']  = ' is over length. ';
Validator.FunctionMessage['LENGTH_OVER']   = ' is under length. ';
Validator.FunctionMessage['REGEXP']        = ' is not match pattern. ';
Validator.FunctionMessage['EMAIL']         = ' is not regal email address. ';
Validator.FunctionMessage['URL']           = ' is not regal url. ';

Validator.Validations = {
	NOT_NULL: {
		name: 'NOT_NULL',

		check: function(value) {
			if (value instanceof Array) {
				for (var i = 0; i < value.length; i++) {
					if (value[i] != "") return true;
				}
				return false;
			} else {
				return value != "";
			}
		}
	},

	check_base: function(pattern, value){
		var regexp = new RegExp(pattern);
		if (value instanceof Array) {
			for (var i = 0; i < value.length; i++) {
				if (value[i] != "" && !regexp.test(value[i])) return false;
			}
			return true;
		} else {
			if (value == "") return true;
			return regexp.test(value);
		}
	},

	INT: {
		name: 'INT',

		check: function(value) {
			return Validator.Validations.check_base(/^\-?\d+$/, value);
		}
	},

	UINT: {
		name: 'UINT',

		check: function(value) {
			return Validator.Validations.check_base(/^\d+$/, value);
		}
	},

	REAL: {
		name: 'REAL',

		check: function(value) {
			return Validator.Validations.check_base(/^\-?\d+(\.\d+)?$/, value);
		}
	},

	UREAL: {
		name: 'UREAL',

		check: function(value) {
			return Validator.Validations.check_base(/^\d+(\.\d+)?$/, value);
		}
	},

	ASCII: {
		name: 'ASCII',

		check: function(value) {
			return Validator.Validations.check_base(/^[\x21-\x7E]+$/, value);
		}
	},

	LENGTH_UNDER: function(n) {
		return {
			name: 'LENGTH_UNDER',

			check: function(value) {
				if (value instanceof Array) {
					for (var i = 0; i < value.length; i++) {
						if (value[i] != "" && value[i].length < n) return true;
					}
					return false;
				} else {
					if (value == "") return true;
					return value.length < n;
				}
			}
		};
	},

	LENGTH_OVER: function(n) {
		return {
			name: 'LENGTH_OVER',

			check: function(value) {
				if (value instanceof Array) {
					for (var i = 0; i < value.length; i++) {
						if (value[i] != "" && value[i].length > n) return true;
					}
					return false;
				} else {
					if (value == "") return true;
					return value.length > n;
				}
			}
		};
	},

	REGEXP: function(p) {
		return {
			name: 'REGEXP',

			check: function(value) {
				return Validator.Validations.check_base(p, value);
			}
		}
	},

	EMAIL: {
		name: 'EMAIL',

		check: function(value) {
			return Validator.Validations.check_base(/[!#-9A-~]+@+[a-z0-9]+.+[!#-9A-~]/i, value);
		}
	},

	URL: {
		name: 'URL',

		check: function(value) {
			return Validator.Validations.check_base(/https?:\/\/[!#-9A-~]+\.+[a-z0-9]\/?/i, value);
		}
	}
}