/* QUICK FILTER */
Ext.tree.QuickFilter = function(tree){
    Ext.tree.QuickFilter.superclass.constructor.call(this);
};

Ext.extend(Ext.tree.QuickFilter, Ext.util.Observable, {
	init: function(tree) {
		this.active=false;
		this.tree = tree;
		this.node = null;
	},
	getNode: function() {
		var selNodes = this.tree.getSelectionModel().selNodes;
		if (!selNodes) selNodes = [this.tree.getSelectionModel().selNode];
        var n = null;
		if (selNodes.length>0) {
			n = selNodes[0];
			for (var i=1; i<selNodes.length; i++)
				if (n.getDepth()>selNodes[i].getDepth()) n = selNodes[i];
			n = (n.attributes.leaf ? n.parentNode : n);
		}
		return n;
	},
    run : function() {
		if (n = this.getNode()) {	/* a node was found */
			if (this.active && this.node!=n) this.remove();
			else if (this.active && this.node==n) {
				this.field.focus();
				return;
			}
			
			var _this = this;
			this.node=n;
			this.active=true;
			
			this.container = Ext.DomHelper.append(this.node.getUI().getTextEl().parentNode.parentNode.id,{
				tag: 'span', cls: 'baf-quick-filter x-small-editor'
		    },true);
		    
			this.field = Ext.DomHelper.append(this.container.id,{
				tag: 'input', type: 'text', cls: 'x-form-text x-form-field'
			},true);
	    	
			this.focus();
			
			// add events
			this.field.addListener('keyup',function(e) {
				switch(e.getKey()) {
					case e.ESC:
						_this.remove(); break;
					default:
						var k = e.getKey();
						if ((k<=122 && k>=45) || k==8) {
							var text = _this.field.getValue();
							var re = new RegExp(Ext.escapeRe(text), 'i');
							_this.filter(_this.node,re,text,0);
						}
				}
			});
		}
    },
    filter: function(n,re,text,level) {
    	
    	if (text.length==0) {
			this.resetFilter(); return;
		}
    	
    	if (n.isLoaded()) n.expand(false,false);
    	
    	var hasChildren = false;
    	for (var i=0; i<n.childNodes.length; i++) {
			hasChildren = (this.filter(n.childNodes[i],re,text,level+1) || hasChildren);
    	}
    	if (level!=0) {
	    	if (!re.test(n.attributes.name)) {
	    		if (!hasChildren) {
	    			n.ui.hide();
	    			return false;
	    		} else {
	    			n.ui.show();
	    		}
	    	} else {
	    		n.cascade(function(n){
	    			n.ui.show();
	    			n.collapse(false,false);
	    		});
	    	}
    	}
    	return true;
    },
    resetFilter: function() {
    	if (this.node) {
	    	this.node.cascade(function(n){
    			n.ui.show();
    			if (n.isLoaded()) n.expand(false,false);
    		});
    	}
    },
    focus: function() {
    	this.field.focus();
    },
    remove: function() {
    	if (this.container) {
    		this.container.remove();
    		this.resetFilter();
    		this.active = false;
    		this.node = null;
    	}
    }
});

/**
 * @class Ext.tree.SearchToolbar
 * @extends Ext.Toolbar
 * A specialized toolbar that provides automatic search on a given tree.
 * @constructor
 * Create a new Ext.tree.SearchToolbar
 * @param {Object} config The config object
 */
Ext.tree.SearchToolbar = Ext.extend(Ext.Toolbar, {
	searchText : 'Search',
	searchByText : 'by: ',
	emptySearchByText : '(none)',
	closeButText : 'Close',
	
	fieldIconCls : 'baf-search-icon-onfield',
	fieldWidth : 150,
	
    paramNames : {query: 'searchquery', by: 'searchby', node: 'parent_id'},
    defaultParams : {},
    nodeName : 'name',
    
	menus : null,
	customItems : null,
	
    initComponent : function(){
        this.addEvents('search');
        Ext.tree.SearchToolbar.superclass.initComponent.call(this);
    },

    // private
    onRender : function(ct, position){
        Ext.tree.SearchToolbar.superclass.onRender.call(this, ct, position);
        
        this.itemsTb = [];
        
        this.closeBut = this.addButton({
            tooltip: this.closeButText,
            iconCls: "baf-search-close-button",
            handler: this.onClick.createDelegate(this, ["close"])
        });
        this.itemsTb.push(this.closeBut);
        
        this.searchText = this.addText(this.searchText);
        this.itemsTb.push(this.searchText);
        
        this.rawField = this.addField(new Ext.form.TextField({
	        width: this.fieldWidth,
	        cls: this.fieldIconCls
	    }));
		this.field = Ext.get(this.rawField.el);
	    this.field.on("keydown", this.onSearchKeydown, this);
	    this.field.on("focus", function(){this.dom.select();});
	    this.itemsTb.push(this.field);
	    
	    if (this.menus) {
	        this.searchBy = this.addButton({
	            text: this.searchByText,
		        menuAlign: 'bl-tl?'
	        });
	        this.itemsTb.push(this.searchBy);
	    }
	    // add custom items
	    if (this.customItems) {
	    	for (var i=0; i<this.customItems.length; i++) {
	    		this.add('->',this.customItems[i]);
	    	}
	    }
    },
    
    // private
	afterRender : function(){
		Ext.tree.SearchToolbar.superclass.afterRender.call(this);
		this.active=true;
		this.deactivate();
		this.updateSearchByText();
	},
	
	activate : function() {
		if (!this.active) {
			this.active = true;
			if (!this.customItems) {
				this.show();
				if (this.ownerCt) {
					var h = this.ownerCt.body.getSize().height;
					h -= this.getSize().height;
	                this.ownerCt.body.setHeight( h);
	                this.ownerCt.doLayout();
				}
			} else {
				for (var i=0; i<this.itemsTb.length; i++) {
					this.itemsTb[i].show();
				}
			}
		}
		if (Ext.isIE) this.updateSearchByText();		/* IE fix */
		this.focusTb();
	},
	
	deactivate : function() {
		if (this.active) {
			this.active = false;
			if (!this.customItems) {
				if (this.ownerCt) {
					var h = this.ownerCt.body.getSize().height;
					h += this.getSize().height;
	                this.ownerCt.body.setHeight( h);
	                this.ownerCt.doLayout();
				}
				this.hide();
			} else {
				for (var i=0; i<this.itemsTb.length; i++) {
					this.itemsTb[i].hide();
				}
			}
		}
	},
	
	// private
	focusTb : function() {
		this.rawField.focus();
	},
	
	// private
	enableTb : function() {
		if (this.rawField.disabled) this.rawField.enable();
		if (this.searchBy) {
			if (this.searchBy.disabled) this.searchBy.enable();
		}
	},
	
	// private
	disableTb : function() {
		if (!this.rawField.disabled) this.rawField.disable();
		if (this.searchBy) {
			if (!this.searchBy.disabled) this.searchBy.disable();
		}
	},
	
	// private
    updateInfo : function(){
        if(this.displayEl){
        	if (this.node) this.displayEl.el.innerHTML = ' in "'+this.node.attributes[this.nodeName]+'"';
        	else this.displayEl.el.innerHTML = '';
        }
    },
	
	// private
	updateSearchByText : function(){
    	var t = '';
    	this.searchByParams = [];
    	
    	if (this.searchBy.menu) {
    		var items = this.searchBy.menu.items.items;
		    for (var i=0; i<items.length; i++)
	    		if (items[i].checked) {
	    			if (t.length==0) t += items[i].text;
	    			else t += ', '+items[i].text;
	    			this.searchByParams.push(items[i].dbField);
	    		}
    	}
    	if (t.length==0) t = this.emptySearchByText;
	    this.searchBy.setText(this.searchByText+t);
    },
	
    // public
    set : function(node,menu) {
        if ((typeof node.attributes.allowSearch == 'undefined' || node.attributes.allowSearch===true) && !node.attributes.leaf) {
        	if (this.searchBy) {
        		// make the menu
        		if ((menu===false && this.searchBy.menu) || (menu && !this.menus[menu])) {
        			this.searchBy.menu = null;
        			this.updateSearchByText();
        		} else if (menu && this.menus[menu] && (this.menus[menu] != this.searchBy.menu)) {
        			this.searchBy.menu = this.menus[menu];
        			this.searchBy.menu.addListener('itemclick',function() {
        				this.updateSearchByText();
        			},this,{delay:100});
        			this.searchBy.menu.addListener('hide',function() {
        				this.focusTb();
        			},this,{delay:100});
        			this.updateSearchByText();
        		}
        	}
        	this.enableTb();
        	this.node = node;
        	this.updateInfo();
        } else {
        	if (this.searchBy && this.searchBy.menu) this.searchBy.menu = null;
        	this.disableTb();
        	this.node = null;
        	this.updateInfo();
        }
    },
    
    // private
    onSearchKeydown : function(e){
        if (e.keyCode == e.ESC) {
            e.stopEvent();
            this.deactivate();
        } else if (e.keyCode == e.ENTER) {
        	e.stopEvent();
            this.doLoad();
        }
    },
    
    // private
    setParams : function(n) {
    	var pn = this.paramNames, dp = this.defaultParams, sbp = this.searchByParams, tree = n.getOwnerTree(), loader = tree.loader, o = loader.baseParams;
    	
        if (dp) for (var i in dp) o[i] = dp[i];
        
        o[pn.node] = (tree.idName ? n.attributes[tree.idName] : n.attributes.id);
        if (isNaN(o[pn.node])) delete o[pn.node];
        
        o[pn.query] = this.field.getValue();
        n.attributes.searchedQuery = o[pn.query];
        
        if (sbp.length>0) {
        	for (var i=0; i<sbp.length; i++) {
        		o[pn.by+'['+i+']'] = sbp[i];
        	}
        }
    },
    
    // private
    delParams : function(n) {
    	var pn = this.paramNames, dp = this.defaultParams, sbp = this.searchByParams, tree = n.getOwnerTree(), loader = tree.loader, o = loader.baseParams;
    	
        if (dp) for (var i in dp) o[i] = dp[i];
        
        delete o[pn.query]; delete o[pn.node];
        
        if (sbp.length>0) {
        	for (var i=0; i<sbp.length; i++) {
        		delete o[pn.by+'['+i+']'];
        	}
        }
    },
    
    // private
    doLoad : function(){
    	if (!this.node) return;
        var pn = this.paramNames, dp = this.defaultParams, sbp = this.searchByParams, n = this.node, tree = n.getOwnerTree(), loader = tree.loader, o = loader.baseParams, _this = this;
        
        this.beforeLoad(n);
        
        if (n.isLoaded()) {		/* reload the node */
        	loader.load(n, function() { _this.afterLoad(n); });
        } else {
        	n.expand(false,false,function() { _this.afterLoad(n); });
        }
        
    },
    
    // private
    beforeLoad : function(n) {
    	this.setParams(n);
    	this.disableTb();
    },
    
    // private
    afterLoad : function(n) {
    	this.delParams(n);
    	this.insertClearLoad(n);
    	this.enableTb();
    	if(this.fireEvent('search', this, n) !== false){
            n.expand(true,false);
        }
    },
    
    clearLoad : function(n) {
    	delete n.attributes.searchedQuery;
    	n.attributes.searchClearBut.remove();
    	delete n.attributes.searchClearBut;
    	n.reload();
    },
    
    // private
    insertClearLoad : function(n) {
    	if (n.attributes.searchClearBut) n.attributes.searchClearBut.remove();
    	n.attributes.searchClearBut = Ext.DomHelper.append(n.getUI().getTextEl().parentNode.parentNode.id,{
			tag: 'div', html: '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', title: 'Clear search: \''+n.attributes.searchedQuery+'\'', cls: 'baf-search-clear-filter'
	    },true);
	    n.attributes.searchClearBut.on('click',function(e) {
	    	e.stopEvent();
	    	this.clearLoad(n);
	    },this);
    },
    
    // private
    onClick : function(which){
        switch(which){
            case "close":
                this.deactivate();
            break;
        }
    }
});