/**
 * THIS IS A PATCH TO FIX THE "Unknown runtime error" BUG IN IE. THIS MIGHT
 * NEED CHANGING IF WE UPDATE THE YUI VERSION ON THE SITE. THIS IS FOR 2.6.0
 * 
 * Populates the array of &lt;li&gt; elements in the container with query
 * results.
 *
 * @method _populateList
 * @param sQuery {String} Original request.
 * @param oResponse {Object} Response object.
 * @param oPayload {MIXED} (optional) Additional argument(s)
 * @private
 */
YAHOO.widget.AutoComplete.prototype._populateList = function(sQuery, oResponse, oPayload) {
    // Clear previous timeout
    if(this._nTypeAheadDelayID != -1) {
        clearTimeout(this._nTypeAheadDelayID);
    }
        
    sQuery = (oPayload && oPayload.query) ? oPayload.query : sQuery;
    
    // Pass data through abstract method for any transformations
    var ok = this.doBeforeLoadData(sQuery, oResponse, oPayload);

    // Data is ok
    if(ok && !oResponse.error) {
        this.dataReturnEvent.fire(this, sQuery, oResponse.results);
        
        // Continue only if instance is still focused (i.e., user hasn't already moved on)
        // Null indicates initialized state, which is ok too
        if(this._bFocused || (this._bFocused === null)) {
            
            //TODO: is this still necessary?
            /*var isOpera = (YAHOO.env.ua.opera);
            var contentStyle = this._elContent.style;
            contentStyle.width = (!isOpera) ? null : "";
            contentStyle.height = (!isOpera) ? null : "";*/
        
            // Store state for this interaction
            var sCurQuery = decodeURIComponent(sQuery);
            this._sCurQuery = sCurQuery;
            this._bItemSelected = false;
        
            var allResults = oResponse.results,
                nItemsToShow = Math.min(allResults.length,this.maxResultsDisplayed),
                sMatchKey = (this.dataSource.responseSchema.fields) ? 
                    (this.dataSource.responseSchema.fields[0].key || this.dataSource.responseSchema.fields[0]) : 0;
            
            if(nItemsToShow > 0) {
                // Make sure container and helpers are ready to go
                if(!this._elList || (this._elList.childNodes.length < nItemsToShow)) {
                    this._initListEl();
                }
                this._initContainerHelperEls();
                
                var allListItemEls = this._elList.childNodes;
                // Fill items with data from the bottom up
                for(var i = nItemsToShow-1; i >= 0; i--) {
                    var elListItem = allListItemEls[i],
                    oResult = allResults[i];
                    
                    // Backward compatibility
                    if(this.resultTypeList) {
                        // Results need to be converted back to an array
                        var aResult = [];
                        // Match key is first
                        aResult[0] = (YAHOO.lang.isString(oResult)) ? oResult : oResult[sMatchKey] || oResult[this.key];
                        // Add additional data to the result array
                        var fields = this.dataSource.responseSchema.fields;
                        if(YAHOO.lang.isArray(fields) && (fields.length > 1)) {
                            for(var k=1, len=fields.length; k<len; k++) {
                                aResult[aResult.length] = oResult[fields[k].key || fields[k]];
                            }
                        }
                        // No specific fields defined, so pass along entire data object
                        else {
                            // Already an array
                            if(YAHOO.lang.isArray(oResult)) {
                                aResult = oResult;
                            }
                            // Simple string 
                            else if(YAHOO.lang.isString(oResult)) {
                                aResult = [oResult];
                            }
                            // Object
                            else {
                                aResult[1] = oResult;
                            }
                        }
                        oResult = aResult;
                    }

                    // The matching value, including backward compatibility for array format and safety net
                    elListItem._sResultMatch = (YAHOO.lang.isString(oResult)) ? oResult : (YAHOO.lang.isArray(oResult)) ? oResult[0] : (oResult[sMatchKey] || "");
                    elListItem._oResultData = oResult; // Additional data
                    
                    // PATCH!
                    var children = elListItem.childNodes, n = children.length;
                    while (n--) elListItem.removeChild(children[n]);
                    elListItem.appendChild(document.createTextNode( this.formatResult(oResult, sCurQuery, elListItem._sResultMatch) ));
                    
                    // OLD CODE
                    // elListItem.innerHTML = this.formatResult(oResult, sCurQuery, elListItem._sResultMatch);
                    
                    elListItem.style.display = "";
                }
        
                // Clear out extraneous items
                if(nItemsToShow < allListItemEls.length) {
                    var extraListItem;
                    for(var j = allListItemEls.length-1; j >= nItemsToShow; j--) {
                        extraListItem = allListItemEls[j];
                        extraListItem.style.display = "none";
                    }
                }
                
                this._nDisplayedItems = nItemsToShow;
                
                this.containerPopulateEvent.fire(this, sQuery, allResults);
                
                // Highlight the first item
                if(this.autoHighlight) {
                    var elFirstListItem = this._elList.firstChild;
                    this._toggleHighlight(elFirstListItem,"to");
                    this.itemArrowToEvent.fire(this, elFirstListItem);
                    this._typeAhead(elFirstListItem,sQuery);
                }
                // Unhighlight any previous time
                else {
                    this._toggleHighlight(this._elCurListItem,"from");
                }
        
                // Expand the container
                ok = this.doBeforeExpandContainer(this._elTextbox, this._elContainer, sQuery, allResults);
                this._toggleContainer(ok);
            }
            else {
                this._toggleContainer(false);
            }

            return;
        }
    }
    // Error
    else {
        this.dataErrorEvent.fire(this, sQuery);
    }
        
};


/**
 * Extensions for YUI AutoComplete class
 */

YAHOO.widget.AutoComplete.fromSelect = function(select) {
    var markup,
        inputField,
        resultContainer,
        wrapper,
        options,
        names,
        dataSource,
        autocomplete;
    
    // Generate AutoComplete markup
    markup = Ojay.HTML.div({className: 'autocomplete'}, function(HTML) {
        inputField = HTML.input({type: 'text'});
        resultContainer = HTML.div({className: 'result-list'});
    });
    
    // Hide the <select>
    select = Ojay(select);
    wrapper = Ojay( Ojay.HTML.span({style: {position: 'relative'}}) );
    select.insert(wrapper, 'after');
    wrapper.insert(select);
    select.setStyle({position: 'absolute', left: '-5000px'});
    wrapper.insert(markup, 'after');
    select.on('focus', inputField.focus, inputField);
    
    // Store data from <select>
    names = [];
    options = select.children('option').reduce(function(map, option) {
        var name = option.node.text;
        names.push(name);
        map[name] = option.node;
        return map;
    }, {});
    
    // Create AutoComplete
    dataSource = new YAHOO.util.LocalDataSource(names);
    autocomplete = new this(inputField, resultContainer, dataSource);
    
    autocomplete.forceSelection = true;
    
    // Match at any point in the string
    autocomplete.filterResults = function(query, fullResponse, parsedResponse) {
        var pattern = new RegExp('\\b' + decodeURIComponent(query) + '.*', 'i');
        parsedResponse.results = fullResponse.filter(pattern.test, pattern);
        return parsedResponse;
    };
    
    // Select the correct <option>
    autocomplete.itemSelectEvent.subscribe(function(type, args) {
        var data = args[2];
        select.children('option').set({selected: false});
        options[data].selected = true;
    });
    
    // If user input does not match, ensure the <select> is cleared
    autocomplete.selectionEnforceEvent.subscribe(function(type, args) {
        select.children('option')
            .set({selected: false})
            .at(0).set({selected: true});
    });
    
    // Set initial text value
    var initialValue = (select.children('option').map('node').filter('selected')[0] || {}).text;
    if (/[a-z]/i.test(initialValue)) inputField.value = initialValue;
    return autocomplete;
};

Ojay.HtmlBuilder.include({
    input: Ojay.HTML.input.wrap(function() {
        var args = Array.from(arguments),
            input = args.shift().apply(this, args);
        Ojay(input).addClass(input.type || 'text');
        return input;
    })
});
