var __BA_FORM_VALIDATOR_SETTINGS__ = {
	requiredCName : "required",
	statusSet     : {
		'normal'   : '',
		'hover'    : '_o',
		'disabled' : '_d'
	}
}

function BAFormValidator(node) {
	this.node    = null;
	this.items   = [];
	this.buttons = [];

	this.init(node);
}
BAFormValidator.prototype.init = function(node){
	BARegisterDOMMethodsTo(node);
	this.node = node;

	node.addEventListenerBA("submit", function(e){
		if (!this.isValid()) {
			e.preventDefault();
		}
	}, this);

	node.getElementsByClassNameBA(__BA_FORM_VALIDATOR_SETTINGS__.requiredCName).forEach(function(element){
		this.addItem(new BARequiredFormElement(element));
	}, this);

	node.getElementsByTagNameBA("input").filter(function(node){
		var type = node.getAttributeBA("type").toLowerCase();
		if (type == "submit" || type == "image") {
			var button = new BASubmitButton(node, __BA_FORM_VALIDATOR_SETTINGS__.statusSet);
			this.addButton(button);
		}
	}, this);

	this.onChange();
}
BAFormValidator.prototype.addItem = function(item){
	item.addCallBack("onChange", this.onChange, this);
	this.items.push(item);
}
BAFormValidator.prototype.addButton = function(button){
	this.buttons.push(button);
}
BAFormValidator.prototype.isValid = function(){
	return this.items.every(function(item){ return item.isValid() });
}
BAFormValidator.prototype.enable = function(){
	this.buttons.forEach(function(button){
		button.enable();
	});
}
BAFormValidator.prototype.disable = function(){
	this.buttons.forEach(function(button){
		button.disable();
	});
}
BAFormValidator.prototype.onChange = function(){
	if (this.isValid()) {
		this.enable();
	} else {
		this.disable();
	}
}

function BASubmitButton(node, statusSet, excludeCName) {
	this.node = null;
	this.rollover = null;

	this.init(node, statusSet, excludeCName);
}
BASubmitButton.prototype.init = function(node, statusSet, excludeCName){
	BARegisterDOMMethodsTo(node);
	this.node     = node;
	this.rollover = new BARollover(node, statusSet, excludeCName);
/*
	node.addEventListenerBA("mouseover", function(e){
		if (this.isEnable()) {
			this.rollover.setStatus("hover");
		}
	}, this);
	node.addEventListenerBA("mouseout", function(e){
		if (this.isEnable()) {
			this.rollover.setStatus("default");
		}
	}, this);
*/
}
BASubmitButton.prototype.enable = function(node){
	this.node.disabled = false;
	this.rollover.setStatus("default");
}
BASubmitButton.prototype.disable = function(node){
	this.rollover.setStatus("disabled");
	this.node.disabled = true;
}
BASubmitButton.prototype.isEnable = function(){
	return !this.node.disabled
}

function BARequiredFormElement(node) {
	this.node = null;

	this.init(node);
}
BARequiredFormElement.prototype = new BAObservable();
BARequiredFormElement.prototype.init = function(node){
	BARegisterDOMMethodsTo(node);

	if (BA.ua.isWinIE) {
		node.addEventListenerBA("propertychange", function(e){
			var propertyName = window.event.propertyName;
			if (propertyName == "checked" || propertyName == "value" || propertyName == "disabled") {
				this.doCallBack("onChange", this);
			}
		}, this);
	} else {
		node.addEventListenerBA("change", function(e){
			this.doCallBack("onChange", this);
		}, this);
	}

	this.node = node;
}
BARequiredFormElement.prototype.isValid = function(){
	var nodeName = this.node.nodeName.toLowerCase();
	var ret = true;
	if (nodeName == "input") {
		var type = this.node.getAttributeBA("type");
		switch (type) {
			case "text"     :
			case "hidden"   :
			case "password" :
				ret = (this.node.disabled || this.node.value.replace(/(^\s+|\s+$)/g, "") != "");
				break;
			case "checkbox" :
				ret = (this.node.disabled || this.node.checked == true);
				break;
			case "radio"    :
				var name = this.node.getAttributeBA("name");
				if (name) {
					var nodes = document.getElementsByNameBA(name);
					var enableNodes = nodes.some(function(node){ return !node.disabled });
					if (enableNodes.length) {
						ret = enableNodes.some(function(node){ return node.checked });
					} else {
						ret = true;
					}
				} else {
					ret = (this.node.disabled || this.node.checked == true);
				}
				break;
			default :
				break;
		}
	} else if (nodeName == "textarea") {
		ret = (this.node.disabled || this.node.value.replace(/(^\s+|\s+$|\r\n|\r|\n)/g, "") != "");
	} else if (nodeName == "select") {
		ret = (this.node.disabled || this.node.value != "");
	}
	return ret;
}


BAAddOnload(function(){
	document.getElementsByTagNameBA("form").forEach(function(node){
		var required = BAConcatNodeList(
			node.getElementsByClassNameBA(__BA_FORM_VALIDATOR_SETTINGS__.requiredCName, "input"),
			node.getElementsByClassNameBA(__BA_FORM_VALIDATOR_SETTINGS__.requiredCName, "textarea"),
			node.getElementsByClassNameBA(__BA_FORM_VALIDATOR_SETTINGS__.requiredCName, "select")
		);
		if (required.length) {
			new BAFormValidator(node);
		}
	});
});
