var FormManager = Class.create();

FormManager.prototype = {
	initialize: function(options) 
	{	
		this.logging = true;

		this.log('init: start');
		
		this.errors = new Array();
		this.numErrors = 0;
		this.duration = 0.5;
		this.prefix = 'inv_';
		
		this.url = $F('base') + '/rest/check';
		this.params = new Array('json=true');
		
		this.disableErrors = false;
		
		this.requires = options['requires'];
		this.check = options['check'];
		this.links = options['links'];
		this.calls = new Array();
		
		this.queue = new Array();
		
		if (options['calls']) {
			this.calls = options['calls'];
		}
		this.id = options['id'];
		this.idLast = null;
		this.idSend = options['id_send'];
		this.errMsg = options['error'];
		
		this.ignore = this.prefix + this.idSend;
		
		// send form witout page reload
		this.ajaxSend = options['ajax_send'];
		this.ajaxSendUrl = options['ajax_send_url'];
		
		this.linkDatagrid = options['datagrid'];
		
		// init form
		this.form = $(this.id);
		this.formCheck = new Array();
		
		if (!this.form) {
			this.log('init: failed find form id "' + this.id + '".');
			return false;
		}
		this.form.setAttribute('onsubmit', 'return ' + this.id + 'Form.checkForm()');
		
		this.log('init: start check');
		this.initCheck();
		
		if (this.links) {
			this.log('init: start links');
			this.initLinks();
		}
		
		if (this.calls) {
			this.log('init: start calls');
			this.initCalls();
		}
		
		this.log('init: success');
		return true;
	},
	initCheck: function()
	{
		var length = this.check.length;
		var e = 0;
		
		this.log('initCheck: checks number "'+length+'"');
		
		for (var i in this.check) {
			if (typeof this.check[i] == 'string') {
				if (e < length) {
					this.log('initCheck: check: '+i+' eval '+this.check[i]+'.');
					eval(this.check[i].split('"')[0]);
				} else {
					break;
				}
				e++;
			}
		}
	},
	initLinks: function()
	{
		this.log('initLinks: init.');
		
		var id;
		var element;
		var target;
		var func;
		var on;
		
		for (var i in this.links) {
			var link = this.links[i];
			
			if (!link.type) {
				continue;
			};
	
			switch (link.type) {
				case 'change' :
					if (!$(link.target)) {
						this.log('initLinks: link type "change", id "'+link.target+'" not found.');
						continue;
					}
					id = link.id;
					element = $(link.id);
					target = link.target;
					on = link.type;
					
					if (element.type == 'radio') {
						on = 'click';
					}
					func = "changeItem";
					
					this.log('initLinks: id: ' + element + ',on: ' + on + ', func: ' + func + ', target: ' + target);
					this.calls[this.calls.length] = {"id": element, "on": on, "func": func, "target": target};
					break;
				case 'changeKey' :
					if (!$(link.target)) {
						this.log('initLinks: link type "change", id "'+link.target+'" not found.');
						continue;
					}
					id = link.id;
					element = $(link.id);
					target = link.target;
					on = 'keyup';

					func = "changeItem";
					
					this.log('initLinks: id: ' + element + ',on: ' + on + ', func: ' + func + ', target: ' + target);
					this.calls[this.calls.length] = {"id": element, "on": on, "func": func, "target": target};
					break;
				case 'link' :
					// get only strings
					var form = document.forms[link.form];
					element = form[link.row];
					
					this.log('initLinks: row: ' + link.row);
					
					if (!form) {
						this.log('initLinks: failed link form "'+form+'".');
						continue;
					}

					// filter types
					if (typeof element != 'object') {
						element = $(element);
				
						if (!element) {
							this.log('initLinks: failed link form "'+form+'".');
							continue;
						}
					}
					on = 'change';
					id = element;

					target = i;
					
					if (!element[0]) {
						switch (element.type) {
							case 'checkbox' :
								func = function(event) {
									var el = Event.element(event);

									if (el.checked) {
										this.value = el.value;
									} else {
										this.value = '';
									}
								};
								break;
							default :
								func = function(event) {
									this.value = Event.element(event).value;
								};
								break;
						}
						this.log('initLinks: id: ' + id + ',on: ' + on + ', func: ' + func + ', target: ' + target);
						this.calls[this.calls.length] = {"id": id, "on": on, "func": func, "target": target};
					} else {
						// radio
						for (var e in element) {
							if (typeof element[e] != 'function') {
								func = function(event) {
									this.value = Event.element(event).value;
								};
								this.log('initLinks: id: ' + element[e] + ',on: ' + on + ', func: ' + func + ', target: ' + target);
								this.calls[this.calls.length] = {"id": element[e], "on": on, "func": func, "target": target};
							} else {
								break;
							}
						}
					}
					break;
			}
		}
	},
	initCalls: function ()
	{
		this.log('initCalls: init.');
		
		for (var i in this.calls) {
			var call = this.calls[i];

			if (!call.id) { 
				continue;
			}
			if (!$(call.id)) {
				this.log('initCalls: call on element id "'+call.id+'" not found.');
				continue;
			}

			switch (call.on) {
				case 'change' :
					var element = $(call.id);
					
					if (element.type == 'radio') {
						call.on = 'click';
					}
					break;
			}
			this.log('initCalls: id: ' + call.id + ',on: ' + call.on + ', func: ' + call.func + ', target: ' + call.target);
			
			if (call.target) {
				if (!$(call.target)) {
					this.log('initCalls: target id "'+call.target+'" not found.');
				}
				
				Event.observe(call.id, call.on, eval(call.func).bindAsEventListener($(call.target)));
			} else {
				Event.observe(call.id, call.on, eval(call.func));
			}
		}
	},
	createError: function(messbold, mess, errorid, appendid)
	{
		if (this.disableErrors) {
			return;
		}
		var msg = '<p><strong>'+messbold+'</strong><br />'+mess+'</p>';
		
		if (!$(errorid)) {
			if (errorid != this.ignore) this.numErrors++;

			new Insertion.After($(appendid),  '<div id="'+errorid+'" class="error">'+msg+'</div>');
			new Effect.BlindDown(errorid, {duration: this.duration});
		} else {
			if (this.numErrors < 1) this.numErrors++;
			
			Element.update($(errorid), msg);
			
			new Effect.Shake(errorid);
		}
	},
	createErrorBox: function()
	{
		return false;
	},
	deleteError: function(id)
	{
		if(!$(id)) {
			this.log('deleteErorr: failed delete element id "'+id+'" not found.');
			return false;
		}
		var e = $(id).parentNode;
	
		new Effect.BlindUp(id, {duration: this.duration, afterFinish: function() {
			e.removeChild($(id));
		}});
		
		if (id != this.ignore) this.numErrors--;
		if (this.numErrors < 0) this.numErrors = 0;
	},
	submitError: function() {
		errbold = this.errMsg[0];
		errmess = this.errMsg[1];

		this.createError(errbold, errmess, this.prefix + this.idSend, this.idSend);
	},
	sendForm: function()
	{
		this.log('sendForm: action "'+this.form.action+'".');
		
		if (this.ajaxSend) {
			this.sendAjax();
			return false;
		}
		return true;
	},
	sendAjax: function()
	{
		this.log('sendAjax: form send.');
		
		var values = new Array;
		var form = document.forms[this.form.name];
		var params = this.params;
		
		for (var i in form) {
			params[params.length++] = i + '=' + form[i].value;
		}
		this.request($F('base') + this.ajaxSendUrl, params, get, this.cbSend);
	},
	clear: function()
	{
		var form = document.forms[this.form.name];
		
		for (var i in form) {
			form[i].value = '';
		}
	},
	checkForm: function()
	{
		var length = 0;
		if (this.requires != null) {
			length = this.requires.length;
		}
		var e = 0;

		for (var i in this.check) {
			if (e == length) break;
			if (typeof this.check[i] == 'string') {
				if (e < length && this.requires[i] != null) {
					eval(this.requires[i]);
				}
				e++;
			}
		}

		if (this.numErrors == 0) {
			this.disableErrors = true;
			this.log('checkForm: success form id "'+this.idSend+'".');
			this.deleteError(this.prefix + this.idSend);
			return this.sendForm();
		}
		this.log('checkForm: failed form id "'+this.idSend+'".');
		this.submitError();
		
		return false;
	},
	checkRange: function(id, min, max, errbold, errmess)
	{
		if (this.errors[id]) {
			if (this.errors[id] != 'range' && this.errors[id] != 'required') {
				return true;
			}
		}
		var value = $(id).value;
		
		if (value.length) {
			if (value.length >= min && value.length <= max) {
				this.errors[id] = false;
				return true;
			} else {	
				this.createError(errbold, errmess, this.prefix + id, id);
				this.errors[id] = 'range';
			}
		} else {
			this.deleteError(this.prefix + id);
			this.errors[id] = false;
		}
		return false;
	},
	checkRequired: function(id, errbold, errmess)
	{
		if (this.errors[id]) {
			if (this.errors[id] != 'required') {
				return;
			}
		}
		if ($(id).value == null || $(id).value == '' || $(id).value.length == 0) {
			this.createError(errbold, errmess, this.prefix + id, id);
			this.errors[id] = 'required';
		} else {
			this.deleteError(this.prefix + id);
			this.errors[id] = false;
		}
	},
	is: function(func, id, title, message)
	{
		this.idLast = id;
		
		if (this.formCheck[id] || this.queue[id]) {
			if (!this.queue[id]) {
				this.queue[id] = new Array();
			}
			this.queue[id].push(new Array(func, title, message));
			return;
		}
		this.formCheck[id] = new Array(title, message);
		
		this.log('is: check with function "'+func+'" value id "'+id+'".');
		
		this.requestCheck(func, $(id).value, this.cb);
	},
	cb: function(transport, value)
	{
		this.log('cb: get json value "' + value + '".');
		
		var id = this.idLast;
		
		if (value == true) {
			this.log('cb: delete error "'+this.idLast+'".');
			this.deleteError(this.prefix + this.idLast);
			this.errors[id] = false;
			
			if (this.queue[id].length) {
				var que = this.queue[id].shift();
				this.formCheck[id] = new Array(que[1], que[2]);

				this.log('is: check with function "'+que[0]+'" value id "'+id+'".');

				this.requestCheck(que[0], $(id).value, this.cb);
				return;
			} else {
				this.queue[id]     = null;
				this.formCheck[id] = null;
			}
		} else {
			this.log('cb: create error "'+this.idLast+'".');
			this.createError(this.formCheck[this.idLast][0], this.formCheck[this.idLast][1], this.prefix + this.idLast, this.idLast);
			this.errors[id] = 'cb';
			
			this.queue[id]     = null;
			this.formCheck[id] = null;
		}
		this.idLast = null;
	},
	cbSend: function(transport, data)
	{
		if (data.status != 'success') {
			this.log('cbSend: send form failed');
			return;
		}
		if (this.linkDatagrid) {
			eval(this.linkDatagrid + '.reloadPages()');
		}
		// clear form
		this.clear();
	},
	request: function(url, params, method, callback)
    {
		var ps = params.join("&");
				 params.pop();
	
       	this.log('request: url "' + url + '?' + ps + '".');
         
    	new Ajax.Request(
	    	url, {
	    		method: method, 
	    		asynchronous: 1,
				parameters: ps, 
	        	onComplete: callback.bind(this),
	        	onFailure: this.fetchError
	   	});
    },
    requestCheck: function(func, value, callback)
    {
    	var params = this.params;
    		params[params.length++] = 'value=' + value;
    	
    	this.request(this.url + '/' + func, params, 'post', callback);
    },
    log: function(message)
	{
		if (this.logging) {
			logDebug('Form::' + message);
		}
	}
}

function toggleFieldset(id)
{
	Element.toggle(id);
	
	var a = $(id + '_a');
	
	if (a.innerHTML == '+') {
		a.innerHTML = '-';
	} else {
		a.innerHTML = '+';
	}
}
