
//================================================
// AutoComplete Manager
//================================================
function AutoCompleteManager() {
    var me = this;
    if (document.addEventListener) {
        document.addEventListener("click",  function(evt) {me._trackActiveElement(evt);},       true);
        document.addEventListener("focus",  function(evt) {me._trackActiveElement(evt);},       true);
    } else {
        document.attachEvent("onclick",  function(evt) {me._trackActiveElement(evt);});
        document.attachEvent("onfocus",  function(evt) {me._trackActiveElement(evt);});
    }
};

/**
* track mouse clicks to close popups
*/
AutoCompleteManager.prototype._trackActiveElement = function(evt) {
    var element = null;
    if (evt && evt.target) { 
        element = evt.target == document ? null : evt.target;
        if(element && element.className.indexOf('autocomplete') == -1) {
            this._close();
        }
    }
}

/**
* the open search popup
*/
AutoCompleteManager.prototype.openPopup = null;
AutoCompleteManager.prototype.openItems = null;

/**
* input timeout (to delay the query while user is writing)
*/
AutoCompleteManager.prototype.timer = null;

/**
* prepared search
*/
AutoCompleteManager.prototype.search = null;

/**
* running query
*/
AutoCompleteManager.prototype.running = false;

/**
* registered searches
*/
AutoCompleteManager.prototype.searches = new Array();

/**
* close the open search popup
*/
AutoCompleteManager.prototype._close = function() {
    if(this.openPopup == null) {
        return;
    }
    clearTimeout(this.timer);
    
    var results = document.getElementById('autocomplete_'+this.openPopup+'_results');
    results.style.display = 'none';
    this.openPopup = null;
    this.search = null;
    
}

/**
* execute the callback function when the user clicked a link
*/
AutoCompleteManager.prototype._action = function(index) {
    var search  = this.searches[this.openPopup];
    var fields  = this.openItems[index];
    
    this._close();
    eval("var func = " + search.callback+";");
    func({id:fields[0],name:fields[1],data:fields[2]});
}

/**
* handle the query results
*/
AutoCompleteManager.prototype._result = function(text, params) {
    var search  = this.searches[this.search];
    
    this.openItems = new Array();
    
    var ul = document.createElement('ul');
    var li = null, a = null;
    
    var me = this;
    
    var hits = 0;
    var lines   = text.split("\n");
    for(var i=0;i<lines.length;i++) {
        fields = lines[i].split("|");
        if(fields.length != 3) {
            continue;
        }
        hits++;
        
        li = document.createElement('li');
        li.className = 'autocomplete';
        
        a = document.createElement('a');
        a.className = 'autocompleteItem';
        a.innerHTML = fields[1];
        eval("a.onclick   = function() { me._action("+i+"); }");
        
        li.appendChild(a);
        ul.appendChild(li);    
        
        this.openItems[i] = fields;
    }
        
    var results = document.getElementById('autocomplete_'+search.id+'_results');
    if(hits > 0) {
        results.style.display = 'block';
        results.innerHTML = "";
        results.appendChild(ul);
        this.openPopup = search.id;
    } else {
        results.style.display = 'none';
        this.openPopup = null;
    }
    
    document.getElementById('autocomplete_'+search.id+'_loader').style.display = 'none';
    
    this.search = null;
    this.running = false;
}

/**
* execute the search query
*/
AutoCompleteManager.prototype._query = function() {
    if(this.running ) {
        return;
    }
    this.running = true;
    var search  = this.searches[this.search];
    var value   = document.getElementById('autocomplete_'+search.id+'_input').value;
    
    // prepare request data
    var params = search.type+'|'+value;
    
    // send request
    var me = this;
    bgTools.doXmlHttpRequest(function(text, params) { me._result(text,params);}, search.url, 'post', params);
}

/**
* start a autocompletion search
*/
AutoCompleteManager.prototype._search = function(id) {
    // check that the search is valid
    if(typeof this.searches[id] == 'undefined') {
        return;
    }
    var search  = this.searches[id];
    var value   = document.getElementById('autocomplete_'+id+'_input').value;
    
    this._close();
    
    if(typeof value == 'undefined' || value == null || value == '' || value.length < 2) {
        return;
    }

    if(this.timer != null) {
        clearTimeout(this.timer);
    }
    
    if(this.search != id) {
        if(this.search) {
            document.getElementById('autocomplete_'+this.search+'_loader').style.display = 'none';
        }
        document.getElementById('autocomplete_'+search.id+'_loader').style.display = 'inline';
    }
    
    this.search = id;
    
    this.timer = setTimeout("AutoComplete._query();",500);
}
    
/**
* register an autocompletion search
*/    
AutoCompleteManager.prototype.register = function(id, type, callback, url) {
    // check if this id is already in use
    if(typeof this.searches[id] != 'undefined') {
        return;
    }
    var search      = {};
    search.id       = id;
    search.type     = type;
    search.url      = url;
    search.callback = callback;
    this.searches[id] = search;
    
    var me = this;
    var input = document.getElementById('autocomplete_'+id+'_input');
    input.onkeyup = function() { me._search(id);};
}

var AutoComplete = new AutoCompleteManager();