
Ext.override(Ext.form.ComboBox, {

	noResultsCls : 'x-combo-list-item',
    noResultsMsg : 'No matching results',
    matchCls : 'x-combo-match',


// private
    initComponent : function(){
        Ext.form.ComboBox.superclass.initComponent.call(this);
        this.addEvents(
            /**
             * @event expand
             * Fires when the dropdown list is expanded
             * @param {Ext.form.ComboBox} combo This combo box
             */
            'expand',
            /**
             * @event collapse
             * Fires when the dropdown list is collapsed
             * @param {Ext.form.ComboBox} combo This combo box
             */
            'collapse',
            /**
             * @event beforeselect
             * Fires before a list item is selected. Return false to cancel the selection.
             * @param {Ext.form.ComboBox} combo This combo box
             * @param {Ext.data.Record} record The data record returned from the underlying store
             * @param {Number} index The index of the selected item in the dropdown list
             */
            'beforeselect',
            /**
             * @event select
             * Fires when a list item is selected
             * @param {Ext.form.ComboBox} combo This combo box
             * @param {Ext.data.Record} record The data record returned from the underlying store
             * @param {Number} index The index of the selected item in the dropdown list
             */
            'select',
            /**
             * @event beforequery
             * Fires before all queries are processed. Return false to cancel the query or set the queryEvent's
             * cancel property to true.
             * @param {Object} queryEvent An object that has these properties:<ul>
             * <li><code>combo</code> : Ext.form.ComboBox <div class="sub-desc">This combo box</div></li>
             * <li><code>query</code> : String <div class="sub-desc">The query</div></li>
             * <li><code>forceAll</code> : Boolean <div class="sub-desc">True to force "all" query</div></li>
             * <li><code>cancel</code> : Boolean <div class="sub-desc">Set to true to cancel the query</div></li>
             * </ul>
             */
            'beforequery' 
        );
        if(this.transform){
            this.allowDomMove = false;
            var s = Ext.getDom(this.transform);
            if(!this.hiddenName){
                this.hiddenName = s.name;
            }
            if(!this.store){
                this.mode = 'local';
                var d = [], opts = s.options;
                for(var i = 0, len = opts.length;i < len; i++){
                    var o = opts[i];
                    var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
                    if(o.selected) {
                        this.value = value;
                    }
                    
                    // remove ® from the text
                    var filteredText1 = this.replaceAll(o.text, '®', '');
                    
                    // remove ™ from the text
					var filteredText2 = this.replaceAll(filteredText1, '™', '');					
                    
					d.push([o.id, value, filteredText2]);
                }
                this.store = new Ext.data.SimpleStore({
                    'id': 0,
                    fields: ['id', 'value', 'text'],
                    data : d
                });
                this.valueField = 'value';
                this.displayField = 'text';
            }
            s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference
            if(!this.lazyRender){
                this.target = true;
                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
                Ext.removeNode(s); // remove it
                this.render(this.el.parentNode);
            }else{
                Ext.removeNode(s); // remove it
            }
        }
        //auto-configure store from local array data
        else if(Ext.isArray(this.store)){
			if (Ext.isArray(this.store[0])){
				this.store = new Ext.data.SimpleStore({
				    fields: ['value','text'],
				    data: this.store
				});
		        this.valueField = 'value';
			}else{
				this.store = new Ext.data.SimpleStore({
				    fields: ['text'],
				    data: this.store,
				    expandData: true
				});
		        this.valueField = 'text';
			}
			this.displayField = 'text';
			this.mode = 'local';
		}

        this.selectedIndex = -1;
        if(this.mode == 'local'){
            if(this.initialConfig.queryDelay === undefined){
                this.queryDelay = 10;
            }
            if(this.initialConfig.minChars === undefined){ 
                this.minChars = 0;
            }
        }        
        
    },
    
    
    // this functions replaces val1 by val2 in the given text.
	replaceAll: function(strText, val1, val2)
	{

		var strReplaceAll = strText;

		if(val1 != null && val2 != null)
		{
			var intIndexOfMatch = strReplaceAll.indexOf(val1);			 

			// Loop over the string value replacing out each matching
			// substring.
			while (intIndexOfMatch != -1)
			{
				// Relace out the current instance.
				strReplaceAll = strReplaceAll.replace(val1, val2);
				 

				// Get the index of any next matching substring.
				intIndexOfMatch = strReplaceAll.indexOf(val1);
			}
		}

		return strReplaceAll;

	},


	/**
	* Over ride doQuery to find any match for the user type sin raw value
	*/
	doQuery : function(q, forceAll){
        
        if(q === undefined || q === null){
            q = '';
        }
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel:false
        };
        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
            return false;
        }
        q = qe.query;
        forceAll = qe.forceAll;
        if(forceAll === true || (q.length >= this.minChars)){
            if(this.lastQuery !== q){
                this.lastQuery = q;
                if(this.mode == 'local'){
                    this.selectedIndex = -1;
                    if(forceAll){
                        this.store.clearFilter();
                    }else{
                    	
                    	// pass true to filter any match
                        this.store.filter(this.displayField, q, true);
                    }
                    this.onLoad();
                }else{
                    this.store.baseParams[this.queryParam] = q;
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            }else{
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    },


	// private
	/**
	* Override the onTypeAhead to not auto select the first match
	*/
    onTypeAhead : function(){

		this.lastSelectionText = ''; 
		this.value='';
        if(this.store.getCount() > 0){		   
            var r = this.store.getAt(0);
            var newValue = r.data[this.displayField];			
            var len = newValue.length;
            var selStart = this.getRawValue().length;
            
            // this is to auto select if the list has one item and collapse the list
            // if the list count is 1 fire the select event
            /*
            var count = this.store.getCount();
			if(selStart != len && count == 1)
			{
				if(r)
				{
					this.onSelect(r, 0);
				}				
				this.collapse();
			}
			*/
			
        }
    },
	
	// private
   setToDefault : function(){
			
		if( this.store.getCount() == 0 || (!this.isExpanded()))
		{
			if(this.getValue()== '' || this.findMatch('text', this.getRawValue())== false)
			{			
				this.setValue('');
				this.blur();
			}
		}
		
    },
	
	//private
	findMatch: function(prop, value){
	var match = false;
	 if(this.store.getCount() > 0){
            this.store.each(function(r){
                if(r.data[prop] == value){
                    match = true;                    
                }
            });
        }
	return match;
	},
	
	onLoad : function(){
		
        if(!this.hasFocus){
            return;
        }
        if(this.store.getCount() > 0){
            this.expand();
            this.restrictHeight();
            if(this.lastQuery == this.allQuery){
                if(this.editable){
                    this.el.dom.select();
                }
                if(!this.selectByValue(this.value, true)){
                    this.select(0, true);
                }
            }else{
                this.selectNext();
                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
                    this.taTask.delay(this.typeAheadDelay);
                }
            }
        }else{
            this.onEmptyResults();
        }
        
		// bold matching text
        var v = this.lastQuery;		
        if(v){
            var items = this.innerList.select('.x-combo-list-item');
            items.each(function(item){
				
				var spl = item.dom.innerHTML.match(new RegExp(v,'ig'));
				if(spl != null && spl.length >0)
				{
					for(var i=0; i<spl.length; i++)
					{
						item.update(item.dom.innerHTML.replace(new RegExp(v, 'ig'), String.format('<span class="{0}">{1}</span>', this.matchCls, spl[i])));
					}
				}                
				
            }, this);
        }

    },
	
	onEmptyResults : function(){
        this.innerList.update(String.format('<div class="{0}">{1}</div>', this.noResultsCls, this.noResultsMsg));
        this.expand();
        this.restrictHeight();
    }

});
