/**
 * Required JQuery 1.3.2
 * Required JSON
 */
var form_debug = false;

function FormJS(fname) {
	var form = null;
	$('form').each(function() {
		if ($(this).hasClass(fname)) {
			form = $(this);
		}
	});
	this.form = form;
	this.url = document.URL;
	this.action = function() {return;};
	this.response = null;
	this._send = function (data) {
		var _this = this;
		if (this.indicator && this.indicator.val) {
			this.oldIndicatorVal = this.indicator.val();
			this.indicator.val('Подождите');
		}
		$.post(_this.url, {'validate': data},
			function(r,s) {
				_this._parseResponse(_this, r, s);
			}
		);
	};
}

FormJS.prototype.set = function(selector) {
	if (selector) {
		this.form = $(selector);
	}
};

FormJS.prototype.setURL = function(url) {
	if (url) {
		this.url = url; 
	}
};

FormJS.prototype.setIndicator = function(indicator) {
	if (indicator && indicator.val) {
		this.indicator = indicator;
	}
};

FormJS.prototype.hide = function() {
	this.form.hide();
};

FormJS.prototype.setAllMessages = function(flag) {
	this.allMessages = flag;
};

FormJS.prototype.registerCallback = function(callback) {
	if (typeof callback == 'function') {
		this.callback = callback;
	}
};

FormJS.prototype.registerAction = function(action) {
	if (typeof action == 'function') {
		this.action = action;
	}
};

FormJS.prototype.unregisterCallback = function() {
	if (this.callback != null) {
		this.callback = null;
	}
};

FormJS.prototype._parseResponse = function(_this, response, s) {
	if (response != '') {
		if (form_debug) {alert(response);}
		this.response = response;
		if ( typeof JSON === "object" && JSON.parse ) {
			response = JSON.parse( response );
		} else {
			response = (new Function("return " + response))();
		}
		var opath;
		$(this.form).find('input, select, textarea').each(function() {
			var name = $(this).attr('name');
			if (name == '') return;
			var m = name.match(/([^\[]+)(((\[\w+\])*)*)/i);
			var parts = new Array(m[1]).concat(m[2].slice(1,-1).split(']['));
			var p = response;
			var path,message = '';
			path = parts.slice(0, 2).join('_');
			for (var i=0;i<parts.length;i++) {
				if (p[parts[i]] === undefined) {
					if (opath == path) {
						var errors = $(this).next();
						if (errors.length){
							while (errors[0].tagName.toLowerCase() != 'br') {
								errors = errors.next(); 
							}
							var d = errors.prev();
							if (d.hasClass('errors')) d.remove();
						}
					}
					if (i <= 1) {p = undefined;}
					break;
				}
				p = p[parts[i]];
			}

			if ($(this).attr('type') == 'radio' && p !== undefined) {
				if (path == opath) {
					$(this).prev().prev().remove(); //input label error br input
				}
			}
			opath = path;
			if (p === undefined) return;
			message = p;

			if (_this.allMessages === false) {
				message = (message[0])?message[0]:message;
			} else {
				message = message.join("\r\n");
			}
			if ($(this).attr('type') != 'radio') 
				$(this).addClass('error');

			var insertBefore = $(this).next();
			while (insertBefore.length && insertBefore[0].tagName.toLowerCase() != 'br') {
				insertBefore = insertBefore.next(); 
			}
			insertBefore.before('<div class="errors">' + message + '</div>');

		});
		if (_this.indicator && _this.indicator.val) {
			_this.indicator.val(_this.oldIndicatorVal);
		}
		$('.error:first').focus();
		_this.action();
		// тут callback 2
	} else {
		if (_this.indicator && _this.indicator.val) {
			_this.indicator.val(_this.oldIndicatorVal);
		}
		/* call callback */
		if (typeof(_this.callback) == 'function') {
			_this.callback();
		}
	}
};

FormJS.prototype.validate = function(fieldset) {
	this.fo = {};
	$(this.form).find('.errors').remove();
	$(this.form).find('.error').removeClass('error');
	var _this = this;
 	$(this.form).find('input[type=text]').each(function(i){_this._prepareInput(_this, this);});
 	$(this.form).find('input[type=file]').each(function(i){_this._prepareInput(_this, this);});
	$(this.form).find('input[type=password]').each(function(){_this._prepareInput(_this, this);});
	$(this.form).find('input[type=hidden]').each(function(){_this._prepareInput(_this, this);});
	$(this.form).find('input[type=radio]:checked').each(function(){_this._prepareInput(_this, this);});
	$(this.form).find('input[type=checkbox]').each(function(){_this._prepareInput(_this, this);});
	$(this.form).find('textarea').each(function(){_this._prepareInput(_this, this);});
	$(this.form).find('select').each(function(){_this._prepareInput(_this, this);});
	if (fieldset) {
		for (k in this.fo) {
			if (k != fieldset)
				delete(this.fo[k]);
		}
	}
	var json = $.toJSON(this.fo);
	if (form_debug) alert(json);
	if (!this._send(json)) {
		return false; /* Показать бы ошибочку тута */
	}
};

FormJS.prototype._prepareInput = function(_this, input) {
	var name = $(input).attr('name');
    var m = name.match(/([^\[]+)(((\[\w+\])*)*)/i);
    var parts = new Array(m[1]).concat(m[2].slice(1,-1).split(']['));
    var p = _this.fo;
    for (var i=0; i<parts.length - 1; i++) {
        p[parts[i]] = p[parts[i]] || {};
        p = p[parts[i]];
    }
    p[parts[i]] =  $(input).val();
};
