Ext.tree.CheckTreePanel = function(config) {
    Ext.tree.CheckTreePanel.superclass.constructor.apply(this, arguments);	
    this.addEvents({'check' : true});
} 
Ext.extend(Ext.tree.CheckTreePanel, Ext.tree.TreePanel, {

	reset : function(){
	 	this.root.setChecked(false, true);
	}
		
});

Ext.tree.CheckTreeLoader = function(config) {
    Ext.tree.CheckTreeLoader.superclass.constructor.apply(this, arguments);	
}

Ext.extend(Ext.tree.CheckTreeLoader, Ext.tree.TreeLoader, {
    createNode : function(attr){
        if(this.applyLoader !== false){
            attr.loader = this;
        }
        attr.uiProvider = Ext.tree.CheckTreeNodeUI;
        return(new Ext.tree.CheckTreeNode(attr));  
    }
 
});

Ext.tree.CheckTreeNode = function(attributes) {
    Ext.tree.CheckTreeNode.superclass.constructor.apply(this, arguments);	
    this.addEvents({'check':true});
    this.checked = attributes.checked === true;
    this.allowUncheckedParent = !(attributes.allowUncheckedParent === false);
	this.allowUncheckedChildren = !(attributes.allowUncheckedChildren === false);
} 

Ext.extend(Ext.tree.CheckTreeNode, Ext.tree.AsyncTreeNode, {

	refreshCheckedState : function(data){
		for(var j=0;j < data.length; j++){
			var node = data[j];
			var node = this.findChild('id',node['id']);
			if (node){
				node.setChecked(data[j]['checked']);
				if(data[j]['children']) node.refreshCheckedState(data[j]['children']);
			}
		}
	},

	getSerializedNodeChecks : function(){
	 	var checks = this.id + ':' + (this.checked ? 1:0);
	    var cs = this.childNodes;
        for(var i = 0, len = cs.length; i < len; i++) {
         	checks += ',';
        	checks += cs[i].getSerializedNodeChecks();
        }
		return checks;	
	},
	
	checkChildren : function(checked, deep){
        var cs = this.childNodes;
        for(var i = 0, len = cs.length; i < len; i++) {
        	cs[i].setChecked(checked, deep);
        }
    },
    
    setChecked: function(checked, deep){
		this.checked = checked;
		this.ui.setChecked(checked);
		if (deep) this.checkChildren(checked, deep);
	},

	onCheck : function(checked){
		if (!this.allowUncheckedParent){
			if (!checked && this.parentNode && !this.allowUncheckedChildren && this.parentNode.isChecked()){
				this.setChecked(true);
			} else {
				this.setChecked(checked);			 
				this.checkChildren(checked, true);
			 	this.fireEvent('check', this, checked);				
			}			
		} else {
			this.checked = checked;
		 	this.fireEvent('check', this, checked);			
		}
	},
	
	isChecked : function(){
		return this.checked;
	}
	
});


Ext.tree.CheckTreeNodeUI = function(node){
    Ext.tree.CheckTreeNodeUI.superclass.constructor.apply(this, arguments);	
}; 
 
Ext.extend(Ext.tree.CheckTreeNodeUI, Ext.tree.TreeNodeUI, {

	initCheckboxEvents : function (){
        Ext.Element.fly(this.checkbox).on('click', this.onCheck, this);
	},
	
	setChecked : function(checked){
		this.checkbox.checked = checked;	
	},
	
	onCheck : function (e){
		this.node.onCheck(this.checkbox.checked);				   					
	},

	render : function(bulkRender){
        var n = this.node;
        var targetNode = n.parentNode ? 
			  n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;        
              //n.parentNode.ui.getContainer() : n.ownerTree.container.dom;
        if(!this.rendered){
            this.rendered = true;
            var a = n.attributes;
        
            // add some indent caching, this helps performance when rendering a large tree
            this.indentMarkup = '';
            if(n.parentNode){
                this.indentMarkup = n.parentNode.ui.getChildIndent();
            }
            
		    var buf = ['<li class="x-tree-node"><div class="x-tree-node-el ', n.attributes.cls,'">',
                '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
                '<img src="', this.emptyIcon, '" class="x-tree-ec-icon">',
                '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),'" unselectable="on">',
				'<input type="checkbox" class="ytree-node-checkbox" ', (a.checked ? "checked=\"checked\"":""),'/>',
                '<a hidefocus="on" href="',a.href ? a.href : "#",'" tabIndex="1" ',
                 a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
                '<ul class="x-tree-node-ct" style="display:none;"></ul>',
                "</li>"];            
                
            if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
                this.wrap = Ext.DomHelper.insertHtml('beforeBegin', 
                                    n.nextSibling.ui.getEl(), buf.join(''));
            }else{
                this.wrap = Ext.DomHelper.insertHtml('beforeEnd', targetNode, buf.join(''));
            }
            this.elNode = this.wrap.childNodes[0];
            this.ctNode = this.wrap.childNodes[1];
            var cs = this.elNode.childNodes;
            this.indentNode = cs[0];
            this.ecNode = cs[1];
            this.iconNode = cs[2];
            this.checkbox = cs[3];
            this.anchor = cs[4];
            this.textNode = cs[4].firstChild;
			if(a.qtip){
               if(this.textNode.setAttributeNS){
                   this.textNode.setAttributeNS("ext", "qtip", a.qtip);
                   if(a.qtipTitle){
                       this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
                   }
               }else{
                   this.textNode.setAttribute("ext:qtip", a.qtip);
                   if(a.qtipTitle){
                       this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
                   }
               } 
            }

            this.initEvents();
            this.initCheckboxEvents();
            //this.renderIndent(); cached above now instead call updateExpandIcon
            this.updateExpandIcon();
        }else{
            if(bulkRender === true) {
                targetNode.appendChild(this.wrap);
            }
        }
    }
});
