﻿(function($) { 

var zz = {};


zz.utils = {
 isArray:function(Object){
	return Object.prototype.toString.call(arr) === "[object Array]"; 
 },		
 regs:{
   email:/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
   number : /^\d+$/,
	numberOrLetter : /^[A-Za-z0-9]+$/,
	//numberAndLetter : //,
	realNumber : /(^\d+\.\d+$|^\d+$)/
 }, 
        
 ruleEngine:(function(){
   function RuleEngine(){  
         var self = this;       
         this.defRules = {
             required:{required:{}},             
             email:{
                email:{}            
             }
                       
         };
         this.validators ={
           
             format:function(value,params){
             		//params:{reg://,msg:''}
                 var res ={};
         
                 res.res = params.reg.test(value);
                 if (res.res == false ){
                     res.msg = params.msg || {};
                  }
         
               return res;
            },
       
             email:function(value){             
               return self.validators.format(value,{reg:zz.utils.regs.email,msg:self.msg["email"]}); 
            },
            
            required:function(value){
               var res ={};
                res.res =  (value != undefined) && (value != null) && (value != "");
                if (res.res == false ){
                     res.msg = self.msg["required"] || {};
                }
               return res;
            },
            
            size:function(value,params){
              
                var res ={res:true};
                if (params.length){
                  res.res = (value.length == params.length); 
                  res.msg = (self.msg["size_length"] || {}).replace("{0}",params.length);  
                  
                }else {
                  
                      res.res = (value.length >= params.min) && (value.length <= params.max);  
                  
                     if (res.res == false ){
                     res.msg = self.msg["size"] || {};       
                       res.msg = res.msg.replace("{0}",params.min).replace("{1}",params.max);                 
                     }
                
                } 
                
                return res;   
            },
            
            number:function(value){
            	return self.validators.format(value,{reg:zz.utils.regs.number,msg:self.msg["number"]}); 
            },            
            
            realNumber:function(value,params){
            	//未处理小数点后几位的限制
            	return self.validators.format(value,{reg:zz.utils.regs.realNumber,msg:self.msg["realNumber"]}); 
            },
            
            numberOrLetter:function(value){
            	return self.validators.format(value,{reg:zz.utils.regs.numberOrLetter,msg:self.msg["numberOrLetter"]}); 
            },
            
            range:function(value,params){
             var res ={res:true};
              
             res.res =  (params.min < value) && (value >params.max);
             
             if (res.res == false ){
                     res.msg = self.msg["range"] || {};
                }
             return res;
            }
          
         };
         
         this.msg = {
            required:"{n}不能为空！",
            email:"email的格式不正确",
            range:"{n}取值要求在[{0},{1}]之间",
            size_length:"{n}要求长度为{0}",
            size:"{n}要求长度在[{0},{1}]之间",
            number:"{n}应以数字组成",
            numberOrLetter:"{n}应以数字或字母组成",
            realNumber:"{n}应为实数"
         };
         
       }
     
       
     RuleEngine.prototype = { 
     
        addRules:function(rules){ 
          $.extend(this.defRules,rules);   
        },

       addValidators:function(valid){ 
          $.extend(this.validators,valid);   

       },
        check:function(value,ruleNames,otherRules){
         
         var self = this; 
         var res ={res:true};
          
          $.each(ruleNames,function(i,name){
            
            // 先从自定义规则中查找规则
            var rule = otherRules[name];
            
            // 找不到则从默认规则中找
            if (rule == undefined){  rule = self.defRules[name]  ;  }

            if (rule != undefined){ 
              res = self.validate(value,rule) ; 
            
              if  (res.res == false)      { return false; }

            }
           });
          
          return res;
        
       },
       
       validate:function(value,rule){ 
         var self = this;
         var res = {res:true};
          
         // 先验证required
         if (rule.required != undefined){
           
           res = this.validators.required(value);
           if (res.res == false){
             return res;
           }
           
         }
         else if ((value == undefined) || (value == null) || (value == "")){
           // 不考虑空的情况
           return {res:true};
         };
         
         
         $.each(rule,function(name,params){

           if(name != "required"){
               
           var valid = self.validators[name]; 
           
           if (valid != undefined) {
           
             res = valid(value,params); 
             if (res.res == false){ return res; } 
            }
           }  
         });
         
         return res;
        
      }
    };
    
     return new RuleEngine();
   
 })()

};
// ---------------------------------------------------------------------------------------------
zz.model ={
     
  dataSet:function(ds,metaData ,dataType){
  
      if (!ds){
        return ;      
      }
     //
     this.ds = ds;
     // {type,name:{type,range:{min,max},format}}
     this.metaData = metaData || {}; 
     
     this.dataType = (dataType)?dataType:"json";
     
     this.data = {}; 
     this.ready =false;
  }
  
};


 zz.model.dataSet.prototype = {
   
    get: function(options,callback) {
 
          var $this = this;
          if(this.ds.params){
              options = this.ds.params;
          } 
          $.post(this.ds.getUrl,options,
  
               function(result){
                
                 if (result){
                    $this.data = result;                  
                    if(result.__result__){
                    	$this.data = result.__result__.data;
                    }
                    $this.ready = true; 
              }
      
       
            callback(result);
       
           },    
  
         this.dataType );
  
        },

 
    getTotalCount: function(options,callback) {
 
           var $this = this;

           $.get(this.ds.countUrl,options,
   
                 function(result){
            
                  $this.count = result.count;
          
                callback(result);
 
               },
   
             this.dataType ); 
        },
        
 
    update: function(options,newVal,callback){
    
             var $this = this;
            $.post(this.ds.updateUrl,options,function(){callback;  $this.dirty = false;},this.dataType );

           },
  
  
   updateBatch: function(option,values,callback){
  
          var $this = this;

          $.post(this.ds.batchUrl,options,function(){callback;  $this.dirty = false;},this.dataType );

      },
 
    del: function(options,callback){
         $.get(this.ds.delUrl,options,callback,this.dataType );

    },
    
  getDatas: function(){
   
   return this.data;
  } 
 
};


var DataSet=function(ds,metaData,dataType){

   return new zz.model.dataSet(ds,metaData,dataType);
 
};



// ----------------------------------------------------------------------------------------------------------------
zz.component = function(){};

zz.component.prototype.attach = function(id){
  alert("attatch");
};

zz.component.prototype.detach = function(){
  alert("detatch");
};
 

zz.control =function(){
  
};


zz.control.prototype= {

   renderTo:function(container,obj){
	 function replace(str){
	     var patten = "";
		 for(var name in obj){
             
	            patten = new RegExp("\\$" + name ,"g");
	      
	            str = str.replace(patten ,obj[name]);
	             
	       }; 
	       
	       return str;
		 
	 };
   
	function handleUnmatch(str){
	  
	   var patten = new RegExp("\\$\\w+","g");  
	   str = str.replace(patten ,"");
	   
	   return str;
	} ;
	function handleAttr(attr){
		 var val = container.attr("@"+attr);
		 if(val){
		    val = replace(val);
		   // debugger;
    	    container.removeAttr("@"+attr);
    	 
    	     container.attr(attr,val);
		 }
    	 
	};
	
     var html,patten;
    
     html =  container.html() + "";
     
     if(typeof obj == "object") {
     
    	 html = replace(html);
       
     }
     else{
     
        html = obj + "";
     }
     
     // @src @href 处理
     patten = /@((href)|(src))/gi;
     html = html.replace(patten , "$1");
    
     //dom属性中的@src @href处理
     handleAttr("src");
     handleAttr("href");
     handleAttr("id");
     handleAttr("value");
     
     html = handleUnmatch(html);
     
     container.html(html);
  }

};



$.extend(zz.control.prototype,zz.component.prototype);



zz.block =function(container){

this.container = container;
};



zz.block.prototype = {
 
  
  render:function(){
    var $this = this;
    
    if (this.container)
    {
      var $container = $(this.container);
       
      if ((this.dataSet != undefined) && (!this.dataSet.ready)){
        
        this.dataSet.get({},function(result){
        
           if(( result.__result__ )&& (result.__result__.__msg__)){
        	   
               
        	   if($this.failHandler) {
        	       $this.handleMsg =  $this.failHandler;
        		    
        	    }
        	   
        	   if($this.handleMsg ){
        	       
        	       $this.handleMsg({msg:result.__result__.__msg__,type:result.__result__.__msg_type__});
        	   }
        	   return;
           } 
           
           $container.children("[block]").each(function(){
             //debugger; 
             var type= $(this).attr("block");
             var data = null;
              if ($(this).attr("field")){
                 data = eval("$this.dataSet.data." +  $(this).attr("field"));  
              }else {
                  data = $this.dataSet.data;
              }
              
             var options={
                     container:$(this),
                     data:data,
                     templ: ($this.templ)? $this.templ[$(this).attr("name")]:{}
             };
             if(!data){
                  
                 if($this.handleEmpty){
                     $this.handleEmpty();
                 }
            	 return;
             }
            	 
             switch(type){
               case "list":
                       $this.renderList(options);

                     break;
               case "mlist":
                    $this.renderMList(options);
                    break;
               case "table":
                     $this.renderTable(options);
                   break;
             
                default:
                    var pass = true;
                    if($this.beforeRender){
                        pass = $this.beforeRender(options,options.data,$(this));
                    }
                    if(pass){ $this.renderTo($(this),options.data);};            
               }
            });
             
            
           
            if( $this.completed){
            	$this.completed();
            }
           
        });
      }
    }
  },
  
  renderList:function(options){
   var $this = this; 
   
    if( !options ) {
        options ={
            container:$this.container,    
            data:this.dataSet.data,
            templ:this.templ
        };
    }
   
   var itemMod = $(options.templ.item);
   var frame = document.createDocumentFragment();
  
     for(var i=0;i<options.data.length;i++){
      

         
        var item =  itemMod .clone(true);
        //item.attr("id",itemMod.attr("id") +i );
        item.removeAttr("id");
        
        if($this.beforeRender){
            var pass =  $this.beforeRender(options,options.data[i],item);
            
            if(!pass) {break;}
         }
        
        this.renderTo(item ,options.data[i]);    
       
        if($this.cachedKey){
            
        	//debugger;
            if(typeof options.data[i] == "object"){
                var key = options.data[i][$this.cached] + "";
                $(item).data(key,options.data[i]);

                
            }
        }
        
        item.show();
       
      frame.appendChild(item[0]);
     
       
     }
     
     
     options.container[0].appendChild(frame);
     
   
  },
  
 renderMList:function(options ){
	  
      if( !options ) {
          options ={
              container:$this.container,    
              data:this.dataSet.data,
              templ:this.templ
          };
      }
      
	 for (var name in data){
		
			//debugger;
		    var itemMod = $(options.templ[name].item);	    	
    	    var frame = document.createDocumentFragment();
    	 
    	
	       $.each(options.data[name],function(i,obj){
	    	//obj 必须是数组
	    	  // debugger;
	            var item =  itemMod .clone(true);
	            //item.attr("id",itemMod.attr("id") +i );
	            item.removeAttr("id");
	            $this.renderTo(item ,obj);           
	            
	            item.show();
	           
	            frame.appendChild(item[0]);	         
	        });
	    
	        var parent = $(options.templ[name].container);
            parent[0].appendChild(frame);
           
	   
		 
	 }  
	 
	  
  },  
  renderTable:function(){
     var dataSet = this.dataSet;
     
     var rowTempl =  $(this.templ.row);
   
      
     var frame = document.createDocumentFragment();
     
     for(var i=0;i<this.dataSet.data.length;i++){
      
        var row= rowTempl.clone();
        row.attr("id",rowTempl.attr("id") +i );

       var cols = row.children("td");
       var item;
    
       for (var j=0;j<this.dataSet.data[i].length;j++){
       
        item =  this.dataSet.data[i][j];
        
        if(typeof(item) == "object" ){
           this.renderTo(cols.eq(j) ,item);
           
        } else{
        
            cols.eq(j).html(item);
        }
        
        row.show();
         
       }
       
     
       frame.appendChild(row[0]); 
     }
     
    $(this.templ.table)[0].appendChild(frame);
     
  }
 
  
}; 

$.extend(zz.block.prototype,zz.control.prototype);


var Block = function(container,blockInstances){
 
 
  var ablock = new zz.block(container);
  $.extend(ablock,blockInstances);   
  
  return ablock;
  
};



zz.frame =function(containerId){ 
  this.blocks = new Array();
  
}; 



zz.frame.prototype ={};


$.extend(zz.frame.prototype,zz.control.prototype);


var Frame = function(containerId,frameInstances){

  var aframe = new zz.frame(containerId);
  
  $.extend(aframe ,frameInstances);   
  
  return aframe ;
  
};


window.ZZUI={
  Block:Block,
  Frame:Frame,
  DataSet:DataSet
};

window.zzRuleEngine = zz.utils.ruleEngine;

})(jQuery);


