var FormValidate = Class.create();
FormValidate.prototype = {
	initialize: function(opt) {
		
		var opts = Object.extend({
	      callBack:       	false,
	      callOnFailure:	false,
	      timer:          	500,
	      method:			'post',
	      update:			'parent'
	    }, arguments[1] || {});
		
		this.options = opts;
		
		this.el = $(arguments[0]);
		this.els = new Array();
		this.validateForm = this.validate.bindAsEventListener(this);
		this.el.onsubmit = function(){
			return false;
		}
		this.cunstructEls();
		Event.observe(this.el, "submit", this.validateForm );
	},
	cunstructEls: function (){
		els = [];
		this.el.descendants().each(function(el){
			if(Element.readAttribute(el, 'validate')){
				obj = {	element:el,
						validation: function(){
							returnData = true;
							Element.readAttribute(el, 'validate').split(' ').each(function(s){
								if(s.indexOf('_')>=0){
									sval = s.split('_')[0]+'_x';
								}else{
									sval = s;
								}
								if(Object.isFunction(FormValidate.prototype[sval])){
									if(s.indexOf('_')>=0){
										elval =  el.value.toJSON() + ',"' + s.split('_')[1] + '"';
									}else{
										elval =  el.value.toJSON();
									}
									if(!eval('FormValidate.prototype.'+sval+'('+elval+')')){
										returnData = false;
									}
								}								
							});
							return returnData;
							},
							txt:'Not Valid.',
							hasBox:false
						};
				if(Element.readAttribute(el, 'title')){
					obj.txt = Element.readAttribute(el, 'title');
					el.title = "";
				}			
				els.push(obj);
			}	
		});
		this.els = els;
	},
	
	validate: function (){
		this.clearForm(this.el);
		submit = true;
		this.els.each(function(o) {
		  	if(!o.validation()){
		  		o.element.addClassName('error');
		  		FormValidate.prototype.errorBox(o);
		  		submit = false;
		  	}
		});
		if(submit){
			this.submitForm();
		}
	},
	clearForm: function(el){
		$$(".errorTip").each(function(e){
			Effect.Puff(e,{queue:'end',duration:.6});
		});
	
		$$(".error").each(function(e){
			Element.removeClassName(e, 'error');
		});
	},
	submitForm: function(){
		
		sub = this.options;
		
		if(sub.callBack){
			sub.callBack = (sub.callBack.indexOf("(")<0)?sub.callBack+'()':sub.callBack;
		}
		form = this.el;
		
		new Ajax.Request(form.action, {
			  method: sub.method,
			  parameters: form.serialize(true),
			  requestHeaders: {Accept: 'application/json'},
			  onSuccess: function(transport){
			  	obj = (sub.update=='parent')?form:$(sub.update);
			  	response = transport.responseText;
			  	
			  	if(response.status){
			  		html = response.html;
			  		obj = (response.obj)?$(response.onj):obj;
			  		stop = (response.status=='failed')?true:false;
			  		objClass = (response.className)?response.className:obj.className; 
			  	}else{
			  		html = response;
			  		stop = false;
			  		objClass = obj.className;
			  	}
			  	
			  	if(obj.style.display!='none'){
			  		Effect.Fade(obj,{duration:.5});
			  	}
			  	
			  	fct = function(){
			  		obj.update(html);
			  		obj.className = objClass;
			  		Effect.Appear(obj);
			  		clearTimeout(d);
			  	}
			  	
			  	d = fct.delay(1);
			  	
			  	if(sub.callBack&&!stop){
			  		setTimeout(sub.callBack,sub.timer);
			  	}
			  				  	
			  },
			  onFailure: function(){
				  alert('2');
			  	if(sub.callOnFailure){
			  		setTimeout(sub.callOnFailure,sub.timer);
			  	}
			  }
			});
	},
	number: function(n){
		 var valn = "[0-9]";
		 var regex = new RegExp(valn);
		 return regex.test(n);
	},
	alphaN: function(str){
		 var valn = "^[a-zA-Z0-9]{3}";
		 var regex = new RegExp(valn);
		 return regex.test(str.gsub('\n',' '));
	},
	alphaN_x: function(str,x){
		 var valn = "^[a-z A-Z 0-9 \r]{"+x+"}";
		 var regex = new RegExp(valn);
		 return regex.test(str.gsub('\n',' '));
	},
	email: function(e){
		 var emailReg = "^[\\w-_\.]*[\\w-_\.]\@[\\w]\.+[\\w]+[\\w]$";
		 var regex = new RegExp(emailReg);
		 return regex.test(e);
	},
	errorBox: function(o){
		if(!o.hasBox){
		
			this.errorTip = Builder.node("div", {className: "errorTip", style: "display: none;" }, [
				Builder.node("div", {className: "xboxcontent"}, o.txt) 
			]);
			
			//document.body.insertBefore(this.errorTip, document.body.childNodes[0]);
			Element.insert(document.body,{bottom:this.errorTip});
			Element.clonePosition(this.errorTip, o.element,{setWidth:false,
												setHeight:false,
												offsetLeft:Element.getWidth(o.element)+3,
												offsetTop:-4 
												});
			showBox = this.errorTip;
			o.hasBox = this.errorTip;
		}
		else
		{
			showBox = o.hasBox;
		}
		
		Effect.Appear(showBox,{queue: 'end', duration:.4});
	}
	
}	
