	var CongTemplateEngine = function(template) {
	   if(typeof(template)=='string') {
    	   this.template = template;
	   }
	}
	
	CongTemplateEngine.prototype.template = null;
	CongTemplateEngine.prototype.modifier = null;
	CongTemplateEngine.prototype.params = new CongDirectoryClass();

	CongTemplateEngine.prototype.setParameter = function(key,value) {
	   this.params.put(key,value);
	}
	

	CongTemplateEngine.prototype.getParameter = function(key) {
	   return this.params.get(key);
	}
	
	CongTemplateEngine.prototype.clearParameter = function(key) {
	   return this.params.removeAll();
	}
	
	
	CongTemplateEngine.prototype.getResult = function () {
	   var tmp = this.applyParameter(this.template)
	   var templateLoopParts = this.getLoopTemplateParts(tmp);
	   if(templateLoopParts!=null) {
	   	 tmp = this.processLoop(templateLoopParts)
	   }
	   return tmp;
	}
	
	CongTemplateEngine.prototype.processLoop = function(templateLoopParts) {
	   var result = '';
       var ResultLoop = '';
	   if(templateLoopParts!=null) {
           var val = this.getParameter(templateLoopParts[0]);
           if(val!=null && typeof(val.length)!='undefined') {
               var loopResult = '';
               for(var i=0;i<val.length;i++) {
                   var loopResult = this.applyLoopParameter(i,templateLoopParts[0],templateLoopParts[2]);       
                   ResultLoop += loopResult;
               }
           }
	   }
	   if(ResultLoop!='')  {
	       var lastParts = templateLoopParts[3];
	       result = templateLoopParts[1]+ResultLoop;
	       var parts = this.getLoopTemplateParts(templateLoopParts[3]);	      
	       if(parts!=null) {
	           lastParts = this.processLoop(parts);
	       }
	       result += lastParts;
	   }    
	   return result;	   
	}
	
    CongTemplateEngine.prototype.getLoopTemplateParts = function(template) {
        var res = null;
        var exp = new RegExp("startloop=(\"|')(\\w*)(\"|')",'g');          
        var idx = template.search(exp);
        if(idx>0) {
            res = [RegExp.$2,'','',''];
            var frontPart   = template.substr(0,idx);
            var frontEndIdx = frontPart.lastIndexOf('<');
            res[1] = template.substr(0,frontEndIdx);
            var footpart = template.substr(frontEndIdx);
            exp = new RegExp("endloop=(\"|')"+res[0]+"(\"|')",'g');  
            idx = footpart.search(exp);
            if(idx>0) {
                res[2] = footpart.substr(0,footpart.indexOf('-->',idx)+3);                     
            }
             res[3] = template.substr(res[1].length+res[2].length)
        }
        return res;
    }
    
    CongTemplateEngine.prototype.applyParameter = function(template) {
       var key   = null;
       var value = null;
       var exp   = null;
       var result = new String(template);
       for(var i =0;i<this.params.size();i++) {
           key = this.params.getKey(i);
           value = this.params.getValue(i);

           if(key==null || value==null) return result;
           
           if (typeof(value)!='object' && typeof(value)!='function') {
               exp = new RegExp("\\$"+key+"\\$",'g');
               if(this.modifier!=null) {
                   value = this.modifier(-1,key,null,value);
               }   
               result = result.replace(exp,this.escape(value));
           } else if(typeof(value)=='object') {               
               exp = new RegExp("\\$"+key+"\\.([^\\$]*)\\$",'g'); 
               var idx  = 0;
               var exp2 = null;
               while(true) {
                   idx = result.search(exp);
                   if(idx<0) break;
                   var propname = RegExp.$1;
                   var data = null;
                   try {
                       data = eval("value."+propname);
                   } catch(err) {}  
                   if(data==null || typeof(data)=='undefined') {
                       try {
                         data = eval("value.getAttribute('"+propname+"')");
                       } catch(err) {}  
                   }
                   exp2 = new RegExp("\\$"+key+"\\."+propname+"\\$",'g');  
	               if(this.modifier!=null) {
	                   data = this.modifier(-1,key,propname,data);
	               }   
                   result = result.replace(exp2,this.escape(data));
               }               
           }
       }
      
       return result;
    }    	
	
    CongTemplateEngine.prototype.applyLoopParameter = function(n,key,template) {
       var value = null;
       var exp   = null;
       var result = new String(template);
       value = this.getParameter(key);

       if(key!=null && value!=null && typeof(value.length)!='undefined') {
           var idx  = 0;
           var exp2 = null;
           if(typeof(value)!='object' && typeof(value)!='function' && typeof(value)!='undefined') {
               exp = new RegExp("\\$"+key+"#$",'g'); 
               while(true) {               
                       idx = result.search(exp);                       
                       var data = null;
                       if(idx<0) {
                           break;
                       } else {   
                           data = eval("value["+n+"]");
        	               if(this.modifier!=null) {
        	                   data = this.modifier(n,key,null,data);
         	               } 
                       } 	                           
                       result = result.replace(exp2,this.escape(data));
               }
           } else if (typeof(value)=='object'){
               exp = new RegExp("\\$"+key+"#\\.([^\\$]*)\\$",'g'); 
               while(true) {               
                       idx = result.search(exp);
                       var data = null;
                       if(idx<0) {
                           break;
                       } else {   
                           var propname = RegExp.$1;
                           data = eval("value["+n+"]."+propname);
                           if(data==null || typeof(data)=='undefined') {
                               try {
                                 data = eval("value["+n+"].getAttribute('"+propname+"')");
                               } catch(err) {}  
                           } 
                           exp2 = new RegExp("\\$"+key+"#\\."+propname+"\\$",'g');  
                           if(result.search(exp2)<0) break;
        	               if(this.modifier!=null) {
        	                   data = this.modifier(n,key,propname,data);
         	               } 
                       } 	                           
                       result = result.replace(exp2,this.escape(data));
               }
           }    
           //
           
       } 
       return result;
    }   
    
     	
	CongTemplateEngine.prototype.escape = function(data) {
	     var escapedStr = data;	     
         if(data!=null && typeof(data)=='string') {
              escapedStr = new String(data);
              escapedStr = escapedStr.replace(/&/g,"&amp;");
              escapedStr = escapedStr.replace(/</g,"&lt;");
              escapedStr = escapedStr.replace(/>/g,"&gt;");
        }       	    
        return escapedStr;
	}
	
	
    