/**
 *	javascript form input validator for toolbox web framework
 *	version $Revision: 1.1 $
 *
 *	(c) 2004-2008 MATSUMURA, Masayoshi
 */

var Validator = Class.create({
	initialize: function (form, messages, prefix) {
		this.form = form;
		this.messages = messages;
		this.errorTagIdPrefix = prefix;
	},
	
	action: function (sender) {
		var suffix = "";
		if ("string" == typeof(sender)) {
			var o = $(sender);
			if (o)
				sender = o;
			else {
				if (sender.match(/\[\]$/)) {
					suffix = "[]";
					sender = sender.replace(/\[\]$/, "");
				}
				var name = sender.replace(/\[\d+\]$/, "");
				var index = sender.match(/^.*(\[\d+\])$/)
						? RegExp.$1
						: "";
				if (this.form[name].Children) {
					for (var e in this.form[name].Children) {
						name = e + index;
						break;
					}
					sender = $(name);
				}
				
				if ("string" == typeof(sender))
					sender = null;
			}
		}
		if (! sender || ! sender.name)
			return null;

		var name = sender.name.replace(/\[\]$/, "").replace(/\[\d+\]$/, "");
		var index = sender.name.match(/^.*(\[\d+\])$/)
						? RegExp.$1
						: "";
		var config = this.form[name];
		if (config) {
			config.id = name + index;
			config.suffix = suffix;
			return this.validateItem(config, sender);
		}
		else {
			for (var e in this.form) {
				if (this.form[e].Combo) {
					for (var i = 0; i < this.form[e].Combo.names.length; i++) {
						if (this.form[e].Combo.names[i] == name) {
							config = this.form[e];
							config.id = e + index;
							this.pending = {
								config: config,
								targets: [ ]
							};
							for (var i = 0; i < config.Combo.names.length; i++) {
								this.pending.targets.push($(config.Combo.names[i] + index));
							}
							
							this.pending.object = this.comboObject(e, index, config.Combo, this.pending.targets);
							return null;
						}
					}
				}
			}
		}
	},
	
	comboObject: function (name, index, combo, targets) {
		var result = $(name + index);
		if (! result)
			return null;
		if ("date" == combo.type) {
			result.value = "";
			if (targets[0].value.match(/\S/) &&
				targets[1].value.match(/\S/) &&
				targets[2].value.match(/\S/)) {

				var vals = combo.Default;
				if (targets[0].value.match(/\S/))
					vals[0] = targets[0].value.strip();
				if (targets[1].value.match(/\S/))
					vals[1] = targets[1].value.strip().replace(/^(\d)$/, "0$1");
				if (targets[2].value.match(/\S/))
					vals[2] = targets[2].value.strip().replace(/^(\d)$/, "0$1");
				result.value = vals.join("/");
			}
		}
		else if ("postalCode" == combo.type) {
			result.value = "";
			if (targets[0].value.match(/\S/) &&
				targets[1].value.match(/\S/)) {

				var vals = combo.Default;
				if (targets[0].value.match(/\S/))
					vals[0] = targets[0].value.strip();
				if (targets[1].value.match(/\S/))
					vals[1] = targets[1].value.strip();

				result.value = vals.join("-");
			}
		}
		else if ("phoneNumber" == combo.type) {
			result.value = "";
			if (targets[0].value.match(/\S/) &&
				targets[1].value.match(/\S/) &&
				targets[2].value.match(/\S/)) {

				var vals = [ "", "", "" ];
				if (targets[0].value.match(/\S/))
					vals[0] = targets[0].value.strip();
				if (targets[1].value.match(/\S/))
					vals[1] = targets[1].value.strip();
				if (targets[2].value.match(/\S/))
					vals[2] = targets[2].value.strip();
				result.value = vals.join("-");
			}
		}
		
		return result;
	},
	
	check: function (sender) {
		if (this.pending) {
			for (var i = 0; i < this.pending.targets.length; i++) {
				if (sender == this.pending.targets[i])
					return false;
			}
			this.validateItem(this.pending.config, this.pending.object);
			this.pending = null;
			return true;	// validateItemを実行したらtrue
		}
		return false;
	},
	
	validateItem: function (config, target) {
		this.hideError(config);
		return (this.validItems[config.id] = this.validateEach(config, target));
	},
	
	validateEach: function (config, target) {
		//var id = target.id.replace(/:\d+/, "") + config.suffix;
		var id = target.name;
		var value = $VALUE(id);
		if (null == value)
			alert(id + " == null");
			
		if (config.Required && ! this.required(config, value, target.type))
			return false;
			
		if (config.RequiredIf && ! this.requiredIf(config, value, target.type))
			return false;
			
		if (0 == value.length)
			return true;
		
		if (config.MaxLength && (config.MaxLength > 0) && ! this.maxlength(config, value))
			return false;
			
		if (config.Pattern && ! this.pattern(config, value))
			return false;
		
		if (config.Date && ! this.date(config, value))
			return false;
			
		if (config.DependentChars && ! this.dependentChars(config, value))
			return false;
		
		if (config.EQ && ! this.eq(config, value))
			return false;
		
		if (config.ValidWhen && ! config.ValidWhen(this, config, value, target))
			return false;

		return true;
	},
	errorTag: function (config) {
		var id = config.id;
		if (config.ErrorTo) {
			id = config.ErrorTo;
			if (config.id.match(/(\[\d+\])/))
				id += RegExp.$1;
		}
		return $(this.errorTagIdPrefix + id);
	},
	
	required: function (config, value, type) {
		if (0 == value.length) {
			if (In(type, [ "radio", "checkbox", "select-one" ]))
				return this.showError(config, config.RequiredError, this.messages.REQUIRED2);

			return this.showError(config, config.RequiredError, this.messages.REQUIRED);
		}
		return true;
	},
	
	requiredIf: function (config, value, type) {
		if (0 == value.length) {
			var required;
			if ("undefined" == typeof(config.RequiredIf["OR"])) {
				required = true;
				for (var name in config.RequiredIf) {
					var id = name;
					if (config.id.match(/(\[\d+\])$/))
						id += RegExp.$1;
					
					if (config.RequiredIf[name] != $VALUE(id)) {
						required = false;
						break;
					}
				}
			}
			else {
				required = false;
				for (var name in config.RequiredIf) {
					if ("OR" == name)
						continue;
						
					var id = name;
					if (config.id.match(/(\[\d+\])$/))
						id += RegExp.$1;
				
					if (required = (config.RequiredIf[name] == $VALUE(id)))
						break;
				}
			}
			
			if (required) {
				if (In(type, [ "radio", "checkbox", "select-one" ]))
					return this.showError(config, config.RequiredError, this.messages.REQUIRED2);

				return this.showError(config, config.RequiredError, this.messages.REQUIRED);
			}
		}
		return true;
	},
	
	maxlength: function (config, value) {
		if (value.length > config.MaxLength)
			return this.showError(config, config.MaxLengthError, this.messages.MAXLENGTH);
		
		return true;
	},
	
	pattern: function (config, value) {
		if (value.match(config.Pattern))
			return true;
		
		return this.showError(config, config.PatternError, this.messages.PATTERN);
	},
	
	date: function (config, value) {
		if (! value.match(/^[12]\d{3}\/(?:0[1-9]|1[0-2])\/(?:0[1-9]|[12][0-9]|3[01])$/))
			return this.showError(config, config.PatternError, this.messages.PATTERN);

		var checkValue = toDateStr(value);
		if (value != checkValue)
			return this.showError(config, config.CheckDateError, this.messages.CHECKDATE);
		
		var date = toDate(value);
		var today = toDate();
		if (false === config.FutureDate) {
			if (today < date)
				return this.showError(config, config.FutureDateError, this.messages.FUTUREDATE);
		}
		if (false === config.PastDate) {
			if (date < today)
				return this.showError(config, config.PastDateError, this.messages.PASTDATE);
		}
		return true;
	},
	
	dependentChars: function (config, value) {
		var chars = checkDependentChars(value);
		if (! chars)
			return true;
		
		return this.showError(config, config.DependentCharsError, this.messages.DEPENDENT_CHARS, chars);
	},
	
	eq: function (config, value) {
		var id = config.EQ + (config.id.match(/(\[\d+\])$/)? RegExp.$1: "");
		if ($(id).value.strip() != value) {
			return this.showError(config, config.EQ_Error, this.messages.EQ, this.form[config.EQ].Description);
		}
			
		return true;
	},
	
	showError: function (config, msg, defaultMsg, value) {
		if (this.silent)
			return false;
			
		if (! msg)
			msg = defaultMsg;
		
		msg = format(msg, config.Description, value);
		if (! this.errorTagIdPrefix) {
			alert(msg);
		}
		else {
			var e = this.errorTag(config);
			if (e) {
				if (e.innerHTML.length > 0)
					e.innerHTML += "<br />";
				
				e.innerHTML += msg;
				e.show();
			}
		}
		return false;	//	常にfalse;
	},
	
	hideError: function (config) {
		var e = this.errorTag(config);
		if (e) {
			e.innerHTML = "";
			e.hide();
		}
	},
	
	validItems: { },
	batchMode: false
});


function ValidateForm(validator) {
	//	※配列化未対応
	validator.validItems = { };
	validator.batchMode = true;
	try {
		for (var e in validator.form) {
			if (! validator.form.hasOwnProperty(e))
				continue;
			
			var name = e;
			if (validator.form[e].Combo) {
				var combo = validator.form[e].Combo;
				var targets = [ ];
				for (var i = 0; i < combo.names.length; i++) {
					targets.push($(combo.names[i]));
				}
				validator.comboObject(e, "", combo, targets);
			}
			else if (In(validator.form[e].Type, [ "CheckBox", "CheckBoxTable", "CheckBoxArray" ])) {
				name += "[]";
			}
			if (false === validator.action(name))
				return false;
		}
	
		return true;
	}
	finally {
		validator.batchMode = false;
	}
}

