var ME_Suggestion = function(idField,oOptions){
    
    this.DEFAULT_MIN_CHARS = 2;
    this.DEFAULT_MAX_HEIGHT = 200;
    this.DEFAULT_MAX_RESULTS = 10;
    this.qs = "";
    this.results = null;
    this.mouseOverEnabled = true;
    this._selectedIndex = -1;
    
    this.status = "closed";
    if (!idField)
        throw("Missing param idField");
    
    this.idField = idField;
    this.id  = "ME_Suggestion_"+this.idField;
    if (!document.getElementById(this.idField))
        throw("Element "+idField+" does not exist");
    
    this.field = document.getElementById(this.idField);
    this.qs = this.field.value;
    this.default_value = this.qs;
    disableAutoComplete("#"+this.idField);
    this.field.onkeypress = function(event){return this._disableEnterKey(event)}.bind(this);
    this._setOptions(oOptions); 
    this._createComponents();
    this._attachEvents();
    
    addEvent(window,"unload",function(){purgeDomObj(this)}.bind(this));
}

ME_Suggestion.prototype._disableEnterKey = function(e)
{
     var key;     
     if(window.event)
          key = window.event.keyCode; //IE
     else
        key = e.which; //firefox
    return (key != 13);
}

ME_Suggestion.prototype._setOptions = function(oOptions){
    
    this.options = typeof oOptions == "object" ? oOptions : {};
    
    this.options.maxResults = (typeof this.options.maxResults != "undefined") ? this.options.maxResults : this.DEFAULT_MAX_RESULTS;
    if (this.options.maxResults == 0)
    this.options.selectRowOnOver = (typeof this.options.selectRowOnOver != "undefined") ? this.options.selectRowOnOver : false;
    
    this.options.hideOnMouseOut = (typeof this.options.hideOnMouseOut != "undefined") ? this.options.hideOnMouseOut : false;
    
    this.options.maxHeight = (typeof this.options.maxHeight != "undefined") ? parseInt(this.options.maxHeight) : this.DEFAULT_MAX_HEIGHT; 
    
    this.options.onmouseover = (typeof this.options.onmouseover == "function") ? this.options.onmouseover : function(){};
    this.options.onclick = (typeof this.options.onclick == "function") ? this.options.onclick : function(){};
    
    this.options.onselect = (typeof this.options.onselect == "function") ? this.options.onselect : function(){};
    
    this.options.onsearch = (typeof this.options.onsearch == "function") ? this.options.onsearch : function(){};
    
}

ME_Suggestion.prototype._attachEvents = function(){

    addEvent(this.field,"keyup",this._chooseOperation.bind(this));
    
    //addEvent(this.field,"click",this._getSuggestion.bind(this));
    addEvent(this.field,"blur",this._onblur.bind(this));
    addEvent(this.field,"focus",this._clearHideTimeout.bind(this));
    if (this.options.hideOnMouseOut)
        addEvent(this.field,"mouseout",function(){this._hideDelayed.apply(this,new Array("1000"))}.bind(this));
    addEvent(this.field,"mouseover",this._clearHideTimeout.bind(this));
    
    addEvent(document,"mousemove",function(){this.mouseOverEnabled = true}.bind(this));
    
    if (this.options.hideOnMouseOut)
        addEvent(this.suggestCont,"mouseout",function(){this._hideDelayed.apply(this,new Array("1000"))}.bind(this));
    addEvent(this.suggestCont,"mouseover",this._clearHideTimeout.bind(this));
    
}

ME_Suggestion.prototype._onblur = function(){
    this._hideDelayed.apply(this,new Array("500"));
}

ME_Suggestion.prototype._chooseOperation = function(ev){
    
    var keys = new Array();
    
    keys[13] = "RETURN";
    keys[9] = "TAB";
    keys[27] = "ESC";
    
    keys[112] = "F1";
    keys[113] = "F2";
    keys[114] = "F3";
    keys[115] = "F4";
    keys[116] = "F5";
    keys[117] = "F6";
    keys[118] = "F7";
    keys[119] = "F8";
    keys[120] = "F9";
    keys[121] = "F10";
    keys[122] = "F11";
    keys[123] = "F12";
    
    keys[145] = "SCROLLOCK";
    keys[20] =  "CAPSLOCK";
    keys[144] = "NUMLOCK";
    
    
    keys[16] = "SHIFT";
    keys[19] = "PAUSE";
    keys[18] = "ALT";
    keys[17] = "CTRL";
    
    keys[33] = "PAGEUP";
    keys[34] = "PAGEDOWN";
    keys[35] = "END";
    keys[36] = "HOME";
    
    keys[37] = "ARRSX";
    keys[38] = "ARRUP";
    keys[39] = "ARRDX";
    keys[40] = "ARRDW";
    
    keys[45] = "INS";
    
    //keys[0] = "WIN";
    keys[91] = "LEFTWIN";
    keys[92] = "RIGHTWIN";
    
    var key = (window.event) ? window.event.keyCode : ev.keyCode;
    switch (keys[key]){
        case "ARRDW":
            if (this.status == "closed"){
                this._getSuggestion();
            }
            else
                this._nextRow();
            break;
        case "ARRSX":
        case "ARRDX":
        case "PAGEUP":
        case "PAGEDOWN":
        case "HOME":
        case "SHIFT":
        case "ALT":
        case "WIN":
        case "PAUSE":
        case "CTRL":
        case "END":
        case "INS":        
        case "F1":
        case "F2":
        case "F3":
        case "F4":
        case "F5":
        case "F6":
        case "F7":
        case "F8":
        case "F9":
        case "F10":
        case "F11":
        case "F12":
        case "SCROLLOCK":
        case "CAPSLOCK":
        case "NUMLOCK":
        case "LEFTWIN":
        case "RIGHTWIN":
            break;
        case "ARRUP":
            this._prevRow();
            break;
        case "ESC":
            this.hide(true);
            this.field.blur();
            break;
        case "RETURN":
            if (this.status == "closed"){
                this._getSuggestion();
            }
            else
                this._selectRow(true);
            return false;
            break;
        default:
            this._getSuggestion();
            break;
    }
}

ME_Suggestion.prototype._createComponents = function(){
    
    appendCss("/MESuggestion/ME_Suggestion.css","ME_Suggestion_css");
    
    this.suggestCont = document.createElement("div");
    this.suggestCont.id = this.id+"_container";
    this.suggestCont.className = "ME_Suggestion_container";
    
    this.suggestIframe = document.createElement("iframe");
    this.suggestIframe.id = this.id+"_iframe";
    this.suggestIframe.className = "ME_Suggestion_iframe";
    this.suggestIframe.src = "";
    
    this.resultCont = document.createElement("div");
    this.resultCont.id = this.id+"_results";
    this.resultCont.className = "ME_Suggestion_results";
    this.suggestCont.appendChild(this.resultCont);
    
    this.loaderCont = document.createElement("div");
    this.loaderCont.id = this.id+"_loader";
    this.loaderCont.className = "ME_Suggestion_loader";
    //this.loaderCont.innerHTML = "<img width=\"16\" style=\"width:16px;\" id=\"ME_Suggestion_loader_img\" src=\"/img2/LoadingSmall.gif\" alt=\"loading....\"/>";
    
    this.wrapper = document.createElement("div");
    
    this.wrapper.appendChild(this.suggestIframe);
    this.wrapper.appendChild(this.loaderCont);
    this.wrapper.appendChild(this.suggestCont);

    document.body.appendChild(this.wrapper);
    
    this.setPosition();
    
}

ME_Suggestion.prototype.setPosition = function(){

    var pos = getPosition(this.field);
    var fW = MEgetWidth(this.field);
    var fH = MEgetHeight(this.field);
    var lH = MEgetHeight(this.loaderCont);
    var lW = MEgetWidth(this.loaderCont);
    
    this.suggestCont.style.display = "none";
    this.suggestCont.style.width = fW + "px";
    this.suggestCont.style.position = "absolute";
    this.suggestCont.style.zIndex = "100";
    this.suggestCont.style.top = parseInt(pos.y) + fH + 2 +"px";
    this.suggestCont.style.left = parseInt(pos.x) + "px";
    
    this.suggestIframe.style.backgroundColor = "#FFF";
    this.suggestIframe.style.display = "none";
    this.suggestIframe.style.width = fW + "px";
    this.suggestIframe.style.height = parseInt(MEgetHeight(this.suggestCont)) + "px";
    this.suggestIframe.style.position = "absolute";
    this.suggestIframe.style.zIndex = "100";
    this.suggestIframe.style.top = parseInt(pos.y) + fH + 2 +"px";
    this.suggestIframe.style.left = parseInt(pos.x) + "px";
    this.suggestIframe.style.border="none";
        
    this.loaderCont.style.display = "none";
    this.loaderCont.style.position = "absolute";
    this.loaderCont.style.top = parseInt(pos.y) + fH/2 -lH/2 +"px";
    this.loaderCont.style.left = parseInt(pos.x) + fW - lW +"px";
}

ME_Suggestion.prototype.show = function(){
    this.setPosition();
    this.status = "opened";
    this.suggestCont.style.display = "";
    this.suggestIframe.style.display = "";
}

ME_Suggestion.prototype._clearHideTimeout = function(){
    if (this.hideTimer!="undefined")
        clearTimeout(this.hideTimer);
}


ME_Suggestion.prototype.setCaretPosition = function (oField, iCaretPos) {
    if (!iCaretPos)
        iCaretPos = this.field.value.length;
         
    if (document.selection) { // IE
    
       var oSel = document.selection.createRange ();
       oSel.moveStart ('character', -oField.value.length);
       oSel.moveStart ('character', iCaretPos);
       oSel.moveEnd ('character', 0);
       oSel.select ();
    }
    else
    if (oField.selectionStart || oField.selectionStart == '0') {// Firefox & other
       oField.selectionStart = iCaretPos;
       oField.selectionEnd = iCaretPos;
       oField.focus();
    }
}


ME_Suggestion.prototype._hideDelayed = function(delay){
    this._clearHideTimeout();
    this.hideTimer = setTimeout(function(){this.hide(true)}.bind(this),delay);
}

ME_Suggestion.prototype.hide = function(resetQsField){
    this.suggestCont.style.display = "none";
    this.suggestIframe.style.display = "none";
    if (this._selectedIndex>-1)
        this._unSelectDivRow(this._selectedIndex);
    this._selectedIndex = -1;
    this.status = "closed";
    if (resetQsField)
        this.resetField();
    
}

ME_Suggestion.prototype.resetField = function(){
    if (this.default_value && this.status == "closed"){
        this.field.value = this.default_value;
    }
}

ME_Suggestion.prototype.reset = function(){
    this.default_value = "";
}

ME_Suggestion.prototype._showLoader = function(){
    this.setPosition();
    this.loaderCont.style.display = "";
    this.fieldFocus();
}

ME_Suggestion.prototype._hideLoader = function(){
    this.loaderCont.style.display = "none";
}

ME_Suggestion.prototype._getSuggestion = function(force){
    if (typeof force=="undefined")
        force=false;
    clearTimeout(this.suggTimer);
    this._selectedIndex = -1;
    var minChars = this.options.minChars ? this.options.minChars : this.DEFAULT_MIN_CHARS;
    if (!force && ((this.field.value.length < minChars) || this.checkIfSelected())){
        if (this.field.value.length < minChars)
            this.options.onsearch(this.qs);
        this.hide(false);
        this._hideLoader();
        return;
    }
    
    this._showLoader();
    this.suggTimer = setTimeout(this._makeSuggestionReq.bind(this),500);
}


ME_Suggestion.prototype.checkIfSelected = function(url){
    
    var selText = "";
    if (window.getSelection) {      // Firefox, Opera, Google Chrome and Safari
        if (document.activeElement && 
                (document.activeElement.tagName.toLowerCase () == "textarea" || 
                 document.activeElement.tagName.toLowerCase () == "input")) 
        {
            var text = document.activeElement.value;
            selText = text.substring (document.activeElement.selectionStart, 
                                      document.activeElement.selectionEnd);
        }
        else {
            var selRange = window.getSelection ();
            selText = selRange.toString ();
        }
    }
    else {
        if (document.selection.createRange) {       // Internet Explorer
            var range = document.selection.createRange ();
            selText = range.text;
        }
    }
    
    if (selText !== "")
        return true ;
    else
        return false;
}

ME_Suggestion.prototype.setUrl = function(url){
    this.options.url = url;
}
ME_Suggestion.prototype.getUrl = function(url){
    return this.options.url;
}

ME_Suggestion.prototype._makeSuggestionReq = function(){
    this.options.onsearch(this.field.value);
    var aj = getMEAjaxObj();
    var url = this.options.url;
    
    
    this.qs = this.field.value;
    
    if (url.search(/\?/)==-1)
        url+="?";
    else
        url+="&";
    url+="s="+Url.encode(this.qs);
    
    aj.Request("POST",url,this._manageSuggestionResults.bind(this));
}

ME_Suggestion.prototype._manageSuggestionResults = function(result){
    
    eval("this.response = "+result.responseText);
    this.errors = this.response["errors"];
    this.results = this.all_results = this.response["results"];
    
    
    if (this.errors.length == 0 && this.results){
        var arrayLimit = 0;
        
        if (this.options.maxResults && this.options.maxResults < this.results.length){
            arrayLimit = this.options.maxResults;
        }else
            arrayLimit = this.results.length;
        
        this.results = new Array();
        for (var i=0; i<arrayLimit;i++){
            
            this.results[i] = this.response["results"][i];
        }
        
    }
    
    this._selectedIndex = -1;
    if (this.results)
        this._createResultDiv();
        
    this._hideLoader();
    
    if (this.response["qs"] != this.qs)
        return;
        
    this.show();
    this.fieldFocus();
}

ME_Suggestion.prototype._emptyResults = function(){
    this.suggestCont.innerHTML = "";
}

ME_Suggestion.prototype._setResultDivProps = function(){

    if (this.options.maxResults > 0)
        return;
        
    this.suggestCont.style.height="auto";
    this.suggestCont.style.overflowY="auto";
    this.suggestCont.style.visibility = "hidden";
    this.show();
    var cH = MEgetHeight(this.suggestCont);
    
    if (cH > this.options.maxHeight){
        this.suggestCont.style.height=this.options.maxHeight+"px";
        this.suggestCont.style.overflowY="scroll";
    }else{
        this.suggestCont.style.height="auto";
        this.suggestCont.style.overflowY="auto";
    }
    this.suggestCont.style.visibility = "visible";
    
}

ME_Suggestion.prototype._addEmptyRow = function(){

    var oRow = document.createElement("div");
    oRow.className = "ME_Suggestion_row";
    oRow.innerHTML = "Nessun risultato Trovato";
    this.suggestCont.appendChild(oRow);
    
}

ME_Suggestion.prototype._addRow= function(index){
    
    var row = this.results[index];
    var oRow = document.createElement("div");
    
    oRow.className = "ME_Suggestion_row";
    oRow.innerHTML = row.row_label;
    
    oRow.suggIndex = index;
    
    addEvent(oRow,"click",function(){this._clickRow()}.bind(this));
    if (typeof this.options.onclick == "function")
        addEvent(oRow,"click",function(){this.options.onclick.apply(this,new Array(row))}.bind(this));
    
    addEvent(oRow,"mouseover",function(){this._onRow.apply(this,new Array(row,oRow))}.bind(this));
    if (typeof this.options.onmouseover == "function")
        addEvent(oRow,"mouseover",function(){this.options.onmouseover.apply(this,new Array(row))}.bind(this));
    
    this.suggestCont.appendChild(oRow);
    return oRow;
}

ME_Suggestion.prototype._createResultDiv = function(){
    
    this._emptyResults();
    
    if (this.results.length == 0){
        this._addEmptyRow();
    }
    
    for (var i=0;i<this.results.length;i++){
        this.results[i].domDiv = this._addRow(i);
    }
    
    this._setResultDivProps();
    
}

ME_Suggestion.prototype._selectDivRow = function(oDiv){
    
    oDiv.className = "ME_Suggestion_row_selected";
    var suggIndex = oDiv.suggIndex;
    oDiv.onmouseout = function(){
        this.className= "ME_Suggestion_row";
    }
    this.fieldFocus();
}
    
ME_Suggestion.prototype.fieldFocus = function(){
    this.field.focus();
    this.setCaretPosition(this.field);
}

ME_Suggestion.prototype._unSelectDivRow = function(index){
    if (index > -1)
        if (this.results && this.results.length && this.results[index])
            this.results[index].domDiv.className = "ME_Suggestion_row";
}

ME_Suggestion.prototype._selectRow = function(closeSearch){
    if (this._selectedIndex<0)
        return;
        
    var item = this.results[this._selectedIndex];
    if (item.row_value) {
        this.field.value = item.row_value;
    }
    
    this.qs = this.field.value;
    this.default_value = this.qs;
    
    this.options.onselect(item);
    if (closeSearch)
        this.hide();
}

ME_Suggestion.prototype._clickRow = function(){
    
    this._selectRow();
    this.hide();
}

ME_Suggestion.prototype._onRow = function(item,divRow){
    if (!this.mouseOverEnabled)
        return;
    if (this.options.selectRowOnOver)
        this._selectRow();
    
    this._selectedIndex = divRow.suggIndex;
    this._selectDivRow(divRow);
}

ME_Suggestion.prototype._nextRow = function(){
    
    if (!this.results || this.results.length==0)
        return;
    this.mouseOverEnabled = false;
    if (this._selectedIndex >= this.results.length-1)
        return;
    else
        if (this._selectedIndex > -1)
            this._unSelectDivRow(this._selectedIndex);
    this.show();
    
    var index = ++this._selectedIndex;
    var item = this.results[index];
    
    var divRow = this.results[index].domDiv;
    
    if (this.options.selectRowOnOver)
        this._selectRow();
    
    this._selectDivRow(divRow);
}

ME_Suggestion.prototype._prevRow = function(){
    
    if (!this.results || this.results.length==0)
        return;
    this.mouseOverEnabled = false;
    if (this._selectedIndex <= 0){
        this.hide();
        return;
    }
    else
        this._unSelectDivRow(this._selectedIndex);
    
    this.show();
    
    var index = --this._selectedIndex;
    var item = this.results[index];
    
    var divRow = this.results[index].domDiv;
    
    if (this.options.selectRowOnOver)
        this._selectRow();
    
    this._selectDivRow(divRow);
}
