var FORM = new function() {
	
	this.bind = function(id) {
		var form = (U.isObject(id)) ? id : document.forms[id] || DOM.get(id);
		if (!form) { return null; }
		
		OO.apply(form, this.Form);
		
		return form;	
	}
	
	this.selectValue = function(sel, value) {
		var result = sel.options[sel.selectedIndex].value;
		if (U.def(value)) {
			for (var option,index = 0; (option = sel.options[index]); index++) {
				if (option.value == value) { sel.selectedIndex = index; break; }
			}
		}
		return result;
	}
}

FORM.Form = function() {
	this.oInputs = { };
	this.oTypes = { };
}

FORM.Form.prototype = {

	initSelf: function() {
		this.update();
		EVT.attach(this, 'keyup', this.keyPressFN, this);
	},
	
	update: function() {
		var e, i, input;
		var n, names = [ ];
				
		for (i = 0; ( input = this.elements[i] ); i++) {
			try {
				names.push(input.name.toLowerCase());
				if (!input.registered) this.registerInput(input);
				input.registered = 1;
			} catch(e) { }
		}
		for (n in this.oInputs) {
			if (names.indexOf(n) == -1) {
				i=this.oInputs[n].length-1;
				if (i>=0) do { 
					e = this.oInputs[n][i]; 
					e.onkeypress=e.onchange=e.onclick=e.changeFn=e.set=e.get=null;
				} while (i--);

				delete this.oInputs[n];
				delete this.oTypes[n];
			}
		}
	},
	
	keyPressFN: function(e) { 
		var fn = e.target.changeFn;
		
		if (e.target.form != this) return;

		if (fn) return fn.call(e);
		if (this.changeFn) this.changeFn(e.target); },

	onsubmit: function() { return false; },
	
	returnFalse: function() { return false; },
	
	removeInput: function() {
		for (var name,index = 1; (name = arguments[index]); index++) {
			delete this.oTypes[name];
			delete this.oInputs[name];
		}
	},

	registerInput: function(input) {
		var type, index, input;
		var name = input.name.toLowerCase();
		
		this.oInputs[name] = this.oInputs[name] || [ ];
		this.oInputs[name].push(input);
		
		type = input.tagName.toLowerCase();
		if (input.innovaEditor) {
			this.oTypes[name] = type = 'innova'; 
		} else
			this.oTypes[name] = type = (input.className.indexOf('fck') != -1) ? 'fck' : ((type == 'input') ? input.type.toLowerCase() : type);
		
		if (FORM.initEle[type]) {
			FORM.initEle[type](this, input);
		} else { 
			delete this.oTypes[name];
		}
	},
		
	setOnChange: function(fn, name) {
		if (name) name = name.toLowerCase();
		if (this.oInputs[name]) {	
			var i, input;
			for (i = 0; ( input = this.oInputs[name][i] ); i++) {
				input.changeFn = this.createOnChangeFn(fn, input);
			}
		} else if (!name) {
			this.changeFn = fn;
		}
	},
	
	setFocus: function(name, select) {
		if (name) name = name.toLowerCase();
		if (this.oInputs[name]) {
			try {
				this.oInputs[name][0].focus();
				if (select)this.oInputs[name][0].select();
			} catch(e) { }
		}
	},
	
	createOnChangeFn: function(fn, input) {
		var oThis = this;
		
		return function() { return fn.call(input, input); };
	},
	
	blockPaste: function(name) {
		if (name) name = name.toLowerCase();
		if (this.oInputs[name]) {	
			var i, input;
			for (i = 0; ( input = this.oInputs[name][i] ); i++) {
				input.onpaste = this.returnFalse;
			}
		} 		
	},
	
	getValue: function(name) {
		name = name.toLowerCase();
		var type = this.oTypes[name];
		if (!type) { return false; }
		
		return FORM.get[type](this.oInputs[name]);//.replace(/(\r\n|\r|\n)/g, '&br;');
	},
	
	setValue: function(name, value) {
		name = name.toLowerCase();
		var type = this.oTypes[name];
		if (!type) { return false; }

		FORM.set[type](this.oInputs[name], value);
		if (type=='checkbox') this.enableCheck(name);
	},
	
	getForm: function(ids) {
		var key;
		var result = { };
		
		if (ids) ids = ids.split(',');
		
		for (key in this.oTypes) {
			if (ids && (ids.indexOf(key) == -1)) continue;
			result[key] = this.getValue(key);
		}
		
		return result;
	},
	
	copy: function(src, dest) {
		this.setValue(dest, this.getValue(src));
	
	},

	swap: function(src, dest) {
		var val = this.getValue(dest);
		
		this.copy(src, dest);
		
		this.setValue(src, val);
	},
	
	enable: function(names) {
		if (!names) return;
		names = names.split(',');
		names.forEach(this.enableInput, this);
	},
	
	disable: function(names) {
		if (!names) return;
		names = names.split(',');
		names.forEach(this.disableInput, this);
	},
	
	enableInput: function(name) {
		var label,inputs = this.oInputs[name.toLowerCase()];
		if (inputs) inputs.forEach(function(input) { input.disabled=0; });
		if (label = DOM.get(this.name+'_'+name)) label.className=label.className.replace('disabled', 'normal');
	},
	
	disableInput: function(name) {
		var inputs = this.oInputs[name.toLowerCase()];
		if (inputs) inputs.forEach(function(input) { input.disabled=1; });
		if (label = DOM.get(this.name+'_'+name)) label.className=label.className.replace('normal', 'disabled');
	},
	
	setForm: function(values) {
		var key;
		
		for (key in values) this.setValue(key, values[key]);
	},
	
	addOption: function(name, title, value) {
		var input = this.oInputs[name.toLowerCase()][0];
		
		title = title.toString().replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
		if (input && input.addSelectOption) input.addSelectOption(title, value);
	},
	
	clearOptions: function(name, n) {
		var input = this.oInputs[name.toLowerCase()][0];
		
		if (input && input.clearSelectOptions) input.clearSelectOptions(n);
	},
	
	flashInput: function(name, c, r) {
		var inputs = this.oInputs[name.toLowerCase()];
		c = c || '#800';
		r = r || 3;
		
		if (inputs) setTimeout(U.FN(this, this.execFlash, inputs, c, r*2), 10);
	},
	
	execFlash: function(inputs, c, r) {
		var bg = (r%2) ? "" : c;
		
		for (var i=0,e;(e=inputs[i]);i++) e.style.backgroundColor=bg;
		
		if (--r) setTimeout(U.FN(this, this.execFlash, inputs, c, r), 300);
	},
	
	onKeyPress: function() { this.form.onChange.call(this); },
	onPaste: function() { this.form.onChange.call(this); },
	
	enableCheck: function(input) {
		if (typeof(input)=='string') input = this.oInputs[input.toLowerCase()][0];
		if (!input) return;
		if ((input.type == 'checkbox') && input.enable) {
			if (input.checked) this.enable(input.enable);
			else this.disable(input.enable);
		}
	},
	
	onChange: function(iter) { 
		var OK = true;
		var form = this.form;
		
		if (!form) return;
		if (!iter) { setTimeout(U.FN(this, this.form.onChange, 1), 10); return; }
		
		form.enableCheck(this);
		
		if (this.changeFn)
			OK = this.changeFn(this);
		
		if ((OK != false) && this.form.changeFn)
			this.form.changeFn(this);
	},
	
	disposeSelf: function() {
		var key,e;

		for (key in this.oInputs) { 
			while (e=this.oInputs[key].pop()) { 
				e.onkeypress=e.onchange=e.onclick=e.changeFn=e.set=e.get=null;
				e.ooState = 'Removed'
				DHTML.removeSelf(e);
			};
			
			delete this.oInputs[key];
		}
		this.changeFn = null;
		this.innerHTML = '';
		DHTML.removeSelf(this);
	}
}


FORM.initEle = new function(form) { 
	
	this.text =
	this.hidden =
	this.textarea =
	this.fck = 
	this.password = function(f, input) {
		input.onpaste = input.oncut = f.onPaste;
		input.onkeypress = f.onKeyPress;
		input.onchange = f.onChange;
	}

	this.checkbox =
	this.radio = function(f, input) { input.onclick = f.onChange; input.enable = input.enable || input.getAttribute('enable'); }
	this.select = function(f, input) { input.onchange = f.onChange; input.addSelectOption = FORM.addSelectOption; input.clearSelectOptions = FORM.clearSelectOptions }
}

FORM.set = new function() {
	this.text =
	this.hidden =
	this.textarea =
	this.password = function(inputSet, value) {
		var val = (inputSet[0].getAttribute('ignoreEntities'))?value:U.decodeEntities(value.toString());
		
		if (val != inputSet[0].value) inputSet[0].value = inputSet[0].lastValue = val;
	}
	
	this.fck = function(inputSet, value) {
		var instance = FCKeditorAPI.GetInstance(inputSet[0].name);
		
		switch (instance.Status) {
			case 1  :	
			case 2  :	instance.SetHTML(value, true);
			default :	inputSet[0].value = value; break;
		}
	}
	
	
	this.select = function(inputSet, value) {
		var sel = inputSet[0];
		
		for (var option,index = 0; (option = sel.options[index]); index++) {
			if (option.value == value) {
				sel.selectedIndex = index;
				break;
			}
		}
	}
	
	this.radio = function(inputSet, value) {
		value = value.toString();
		
		inputSet.forEach(function(radio) { radio.checked = (radio.value == value); });
	}
	
	this.checkbox = function(inputSet, value) {
		values = value.toString().split(',');
		
		inputSet.forEach(function(check) { check.checked = (values.indexOf(check.value) != -1) });
	}
	
	this.innova = function(inputSet, value) {
		innova = inputSet[0].innovaEditor;
		innova.putHTML(value);
	}
	
}

FORM.get = new function() {
	this.text =
	this.hidden =
	this.textarea =
	this.password = function(inputSet) {
		return (inputSet[0].getAttribute('ignoreEntities'))?inputSet[0].value:U.encodeEntities(inputSet[0].value);
	}
	
	this.fck = function(inputSet) {
		var instance = FCKeditorAPI.GetInstance(inputSet[0].name);
		
		return instance.GetXHTML(true);
	}
	
	this.select = function(inputSet) {
		var sel = inputSet[0];
		
		return sel.options[sel.selectedIndex].value;
	}

	this.radio = function(inputSet) {
		result = { value: false };
		
		inputSet.forEach(function(radio) { if (radio.checked) result.value = radio.value });
		
		return result.value;
	}

	this.checkbox = function(inputSet) {
		result = { value: [ ] };
		
		inputSet.forEach(function(check) { if (check.checked) result.value.push(check.value); });
		
		return result.value.join(',');
	}

	this.innova = function(inputSet, value) {
		innova = inputSet[0].innovaEditor;
		return innova.getXHTMLBody();
	}
}

FORM.clearSelectOptions = function(n) { n = n || 0; this.options.length = n; }

FORM.addSelectOption = function(title, value) {
	this.options[this.options.length] = new Option(title, value);
}
