var wh_Form=Class.create();
wh_Form.prototype={initialize:function(form,options){
    var form=$(form);
    this.form=form;
    this.inputs=[];
    this.disabler=[];
    this.sm_msgbox=this._createMsgbox(options["sm_msgbox"]);
    var subHandle=this._get_submitForm(this,options);
    form.onsubmit=function(){
      return subHandle();
    };
  },pushInput:function(input,options){
    var inputObj;
    if(input instanceof wh_Input){
      inputObj=input;
    }else {
      inputObj=new wh_Input(input,options);
    }
    this.inputs[inputObj.id]=inputObj;
    this.inputs.push(inputObj);
  },regDisabler:function(name){
    var arr=this.disabler;
    if(-1==arr.indexOf(name)){
      this.disabler.push(name);
    }
    try{
      $(name).disable();
    }
    catch(e){
    }
  },unregDisabler:function(name){
    var arr=this.disabler;
    for(var i=0;i<arr.length;++i){
      if(arr[i]==name){
        arr.splice(i,1);
        try{
          $(name).enable();
        }
        catch(e){
        }
        return ;
      }
    }
  },uninit:function(){
    this.form=null;
    var inputs=this.inputs;
    for(var i=0;i<inputs.length;++i){
      inputs[i].input=null;
    }
  },_get_submitForm:function(wh_form,options){
    var ch_str=options.checking_str===undefined?"\u6b63\u5728\u68c0\u67e5\u6570\u636e...":options.checking_str;
    return function(){
      var params="";
      var disstr=wh_form._$FDisabler.call(wh_form);
      disstr.length?params+="&"+disstr:void (0);
      wh_form.sm_msgbox.style.display="";
      var inputs=wh_form.inputs;
      var remotes=0;
      var err_obj=null;
      for(var i=0;i<inputs.length;++i){
        var input=inputs[i];
        if(input.isRemote()&&!input.remote_right){
          remotes++;
        }
        var result=input.handle();
        if(!err_obj&&!result){
          err_obj=input;
        }
      }
      if(err_obj){
        wh_form._enable.call(wh_form);
        err_obj.input.focus();
        return false;
      }
      var affix_func=options.affix_func;
      if(affix_func){
        wh_form._enable.call(wh_form);
        if(!affix_func(wh_form.form)){
          wh_form.sm_msgbox.innerHTML="";
          wh_form._enable.call(wh_form,ch_str);
          return false;
        }
      }
      params=wh_form.form.serialize();
      params+="&"+$H(options.params||{}).toQueryString();
      wh_form._disable.call(wh_form,ch_str);
      var send_str=options.sending_str===undefined?"\u6b63\u5728\u63d0\u4ea4\u6570\u636e...":options.sending_str;
      var sendData=wh_form._sendData.bind(wh_form,wh_form,options.url,params,send_str,options.onSuccess||function(){
      });
      var poll=function(wf){
        var inputs=wf.inputs;
        var remote_inputs=[];
        var allRight=true;
        for(var i=0;i<inputs.length;++i){
          if(inputs[i].isRemote()){
            remote_inputs.push(inputs[i]);
          }
        }
        return function(){
          if(remote_inputs.length==0){
            window.clearInterval(wf.timer);
            wf.timer=null;
            if(allRight){
              sendData();
            }else {
              wf._enable.call(wf);
            }
          }else {
            for(var i=0;i<remote_inputs.length;++i){
              if(remote_inputs[i].remote_finish){
                if(!remote_inputs[i].remote_right){
                  allRight=false;
                }
                remote_inputs.splice(i,1);
              }
            }
          }
        };
      }(wh_form);
      if(remotes>0){
        wh_form.timer=window.setInterval(poll,200);
      }else {
        sendData();
      }
      return false;
    };
  },_sendData:function(wh_form,url,param,sending_str,onSuccess){
    wh_form.sm_msgbox.innerHTML=sending_str;
    new Ajax.Request(url,{method:"post",parameters:param,onSuccess:function(req){
        var result=req.responseText;
        onSuccess(result,wh_form);
      },onComplete:function(req){
        wh_form._enable.call(wh_form);
        Element.hide(wh_form.sm_msgbox);
      }});
    return false;
  },_createMsgbox:function(ms_box){
    var box=$(ms_box);
    if(box){
      return box;
    }
    var form=this.form;
    var div=document.createElement("div");
    div.id=form.getAttribute["id"]+"_msg";
    form.up().insertBefore(div,form.nextSibling);
    return div;
  },_enable:function(){
    this.sm_msgbox.innerHTML="";
    this.form.enable();
    var arr=this.disabler;
    for(var i=0;i<arr.length;++i){
      try{
        $(arr[i]).disable();
      }
      catch(e){
      }
    }
  },_disable:function(msg){
    this.sm_msgbox.innerHTML=msg;
    this.form.disable();
  },_$FDisabler:function(){
    var arr=this.disabler;
    var str="";
    for(var i=0;i<arr.length;++i){
      if(!arr[i]){
        continue ;
      }
      str+=arr[i]+"="+encodeURIComponent($F(arr[i]))+"&";
    }
    return str.substr(0,str.length-1);
  }};
var wh_Input=Class.create();
wh_Input.prototype={initialize:function(input_name,options){
    var input;
    if(options.form) input=$(options.form).elements[input_name];
    else input = $(input_name);
    if(!input){
      alert(input_name+" is not exists");
      return ;
    }
    if((input.nodeName+"").toLowerCase()!="input"||"text"!=input.type&&"password"!=input.type){
      alert("'"+input.id+"' is not a valid InputElement!");
      return ;
    }
    if(!options.check){
      alert("wh_Input init failing:\nYou must define options.check!");
      return ;
    }
    this.id=input["id"];
    this.param_name=options["param_name"];
    this.input=$(input);
    var msgbox=$(options.msgbox);
    if(!msgbox){
      msgbox=this._createMsgbox(input);
    }
    this.msgbox=msgbox;
    var rw_str=options.remote_wstr===undefined?"\u503c\u91cd\u590d":options.remote_wstr;
    var showRstr=this.onRight=options.onRight||this._get_showmsgfunc(this,options.rstr||"&nbsp;",options.rclass||"");
    this.onWrong=options.onWrong||this._get_showmsgfunc(this,wstr,options.wclass||"");
    var repeatWrong=this._get_showmsgfunc(this,rw_str,options.wclass||"");
    this.isRemote=this._isRemote(options.url);
    if(this.isRemote()){
      this.remote_right=false;
      this.remote_finish=false;
      var che_str=options.checking_str===undefined?"\u6b63\u5728\u9a8c\u8bc1...":options.checking_str;
      var remoteCheck=this._getRemoteFunc(this,options.url,che_str,showRstr,repeatWrong,$H(options.params||{}).toQueryString(),options.onSuccess||function(){
        alert("complete");
      });
    }
    var wstr=options.wstr===undefined?"\xd7":options.wstr;
    this.handle=this._getHandle(this,options.check,showRstr,this.onWrong,remoteCheck,repeatWrong);
    Event.observe(input,options.event_name||"change",this.handle);
    if(options.onFocus){
      this.onFocus=options.onFocus;
      var _this=this;
      var handle=function(){
        return function(event){
          _this.onFocus(_this);
        };
      }();
      Event.observe(input,"focus",handle);
    }
  },_isRemote:function(url){
    return function(){
      return !!url;
    };
  },_getHandle:function(proto,c_func,r_func,w_func,remoteCheck,remoteWrong){
    return function(e){
      var e=e||window.event;
      if(e&&e.type=="change"){
        proto.remote_right=false;
        proto.remote_finish=false;
      }
      if(proto.msgbox){
      }
      var val=$F(proto.input);
      if(c_func(val,proto.input)){
        r_func(proto,proto.input);
        if(proto.isRemote()){
          if(proto.transport){
            proto.transport.abort();
          }
          remoteCheck();
        }
        return true;
      }else {
        w_func(proto);
      }
      return false;
    };
  },_get_showmsgfunc:function(proto,msg,classname){
    var mb=proto.msgbox;
    return function(obj){
      mb.className=classname;
      mb.innerHTML=msg;
      mb.style.display="";
    };
  },_getRemoteFunc:function(proto,url,checking_str,rfunc,wfunc,params,func){
    return function(){
      proto.msgbox.innerHTML=checking_str;
      proto.msgbox.className="field-validation field-validation-default";
      var param_name=proto["param_name"]||"val";
      var ajaxRequest=new Ajax.Request(url,{method:"get",parameters:param_name+"="+encodeURIComponent(proto.input.value)+"&"+params,onSuccess:function(req){
          var result=req.responseText;
          if(func(result,proto)){
            proto.remote_right=true;
            rfunc(proto);
          }else {
            proto.remote_right=false;
            wfunc(proto);
          }
          proto.remote_finish=true;
        },onComplete:function(req){
          proto.remote_finish=true;
        },onFailure:function(req){
          proto.remote_finish=true;
          alert(req.responseText);
        },on404:function(req){
          alert(req.responseText);
        }});
      proto.transport=ajaxRequest.transport;
    };
  },_createMsgbox:function(input){
    var input=$(input);
    var span=document.createElement("span");
    span.id=input.name+"_msg";
    input.parentNode.insertBefore(span,input.nextSibling);
    return span;
  }};