/* Copied from Search-UI, Thanks to Nigel MOTTE :) */
(function($) {
    $.fn.enableSuggest = function(url, options) {

        var defaults = {
            format: "default",
            queryParameter: "value",
            suggestBoxClass: "suggestContainer",
            closeButtonClass: "close",
            itemSelectedClass: "selected",
            itemHighlightedClass: "highlighted",
            closeLabel: "close",
            autoSubmit: true,
            bodyHideControlsClass: null, //used to hide controls for IE6
            delay: 0,           
            getCurrentScope: function() { return "default"; },
            submitButtonID : null,
            autoHideDelay : 3
        }
        var options = $.extend(defaults, options);

        var buildSuggestBox = function(suggestContext) {
            var box = '<div class="' + escapeHTML(options.suggestBoxClass) + '" style="display:none">';
            box += '<a href="#" class="' + escapeHTML(options.closeButtonClass) + '">'
			+ escapeHTML(options.closeLabel)
			+ '</a>';
            box += '<ul></ul>';
            box += '</div>';
            
            suggestContext.suggestBox = $(suggestContext.input).parent().append(box).find("div").get(0);
            $(suggestContext.suggestBox).find("a." + options.closeButtonClass).bind(
					"click", suggestContext, closeSuggestBox);
        }     
        
        var scopeChanged = function(suggestContext, newScope)
        {
            suggestContext.scope = newScope;
            _closeSuggestBox(suggestContext);        
        }
        
        var getSuggestions = function(suggestContext, onSuccessCallback) {
    
            var thisRequest = ++suggestContext.suggestRequests;

            if (suggestContext.input.value == "") {
                suggestContext.suggestUpdate = thisRequest;
                suggestContext.suggestions = [];
                onSuccessCallback(suggestContext);
                return;
            }
            
            var newScope = options.getCurrentScope()
            
            if(newScope != suggestContext.scope)             
                scopeChanged(suggestContext,newScope);           
                
            var parameters = {};
            parameters[options.queryParameter] = suggestContext.input.value;            
            parameters["scope"] = suggestContext.scope;
                
            $.getJSON(url, parameters,
				function(data) {
//				    //update only with suggestions newer 
//				    //than the ones displayed
//				    if (thisRequest < suggestContext.suggestUpdate)
//				        return;
				    suggestContext.suggestUpdate = thisRequest;
				    suggestContext.suggestions = suggestContext.extractSuggestions(data);
				    onSuccessCallback(suggestContext);
				});
        }

        var extractSuggestionsFromDefault = function(data) {
            return data;
        }


        var extractSuggestionsFromGoogleFormat = function(data) {

            var suggestions = new Array();
            for (i = 0; i < data[1].length; ++i) {
                suggestions.push(data[1][i][0]);
            }

            return suggestions;
        }

        var renderSuggestions = function(suggestions) {
            var suggestionsItems = "";
            $(suggestions).each(function() {
                suggestionsItems += ('<li>' + escapeHTML(this) + '</li>');
            });
            return suggestionsItems;
        }

        var closeSuggestBox = function(event) {
           return _closeSuggestBox(event.data);
        }
        
        var _closeSuggestBox = function(suggestContext) {
         if (suggestContext.options.bodyHideControlsClass && $(document.body).hasClass("ie6"))
                $(document.body).removeClass(suggestContext.options.bodyHideControlsClass);
            $(suggestContext.suggestBox).hide();
            return false;
        }

        var displaySuggestions = function(suggestContext) {

            if (options.delay == 0) {
                getSuggestions(suggestContext, updateSuggestions);
            }
            else if (!suggestContext.inDelay) {

                suggestContext.inDelay = true;
                window.setTimeout(function() {
                    suggestContext.inDelay = false;
                    return getSuggestions.call(this, suggestContext, updateSuggestions);
                }, options.delay);
            }
            
            _beginAutoHide(suggestContext);                    
        }
        
        var _beginAutoHide = function(suggestContext)
        {
            window.clearTimeout(suggestContext.autoClosingTimer);
            suggestContext.autoClosingTimer = window.setTimeout(function(){
                _closeSuggestBox(suggestContext);
			    }, suggestContext.options.autoHideDelay * 1000);
        }

        var updateSuggestions = function(suggestContext) {         
            if (suggestContext.suggestions.length == 0) {
                if (suggestContext.options.bodyHideControlsClass && $(document.body).hasClass("ie6"))
                    $(document.body).removeClass(suggestContext.options.bodyHideControlsClass);
                $(suggestContext.suggestBox).hide();
            }
            else {
                if (suggestContext.options.bodyHideControlsClass && $(document.body).hasClass("ie6"))
                    $(document.body).addClass(suggestContext.options.bodyHideControlsClass);
                $(suggestContext.suggestBox).show();
            }
            var ulElt = $(suggestContext.suggestBox).find("ul");
            ulElt.html(renderSuggestions(suggestContext.suggestions));
            configureSuggestionItems(suggestContext, ulElt);
        }

        var configureSuggestionItems = function(suggestContext, ulElt) {
            ulElt.find("li").each(function() {
                $(this).bind("click", suggestContext.input, onSuggestItemClicked);
                $(this).bind("mouseenter", this, function() {
                    $(this).addClass(options.itemHighlightedClass);            
			        window.clearTimeout(suggestContext.autoClosingTimer);	        
                });
                $(this).bind("mouseleave", this, function() {
                    $(this).removeClass(options.itemHighlightedClass);
                    _beginAutoHide(suggestContext);
                });
            });
        }

        var onSuggestItemClicked = function(event) {
            var input = event.data;
            setInputFromLi(input, this);
            if (options.autoSubmit == true) {
                if(options.submitButtonID == null)
                    $(input).closest("form").submit();
                else
                    $('#'+options.submitButtonID).click();
            } else {
                $(input).parent().find("a." + options.closeButtonClass).trigger('click');
            }
        }
        
        var escapeHTML = function(value) {
            return value
					.replace("&", "&amp;")
					.replace("<", "&lt;")
					.replace(">", "&gt;")
					.replace("\"", "&quot;")
					.replace("'", "&apos;");
        }

        var unescapeHTML = function(value) {
            return value
					.replace("&apos;", "'")
					.replace("&quot;", "\"")
					.replace("&gt;", ">")
					.replace("&lt;", "<")
					.replace("&amp;", "&");
        }

        var selectNextSuggestion = function(input) {
            var getNextWhenNoSelection = function(list) {
                return list.get(0);
            }
            var getNext = $.fn.next;
            _selectSuggestion(input, getNextWhenNoSelection, getNext);
        }

        var selectPreviousSuggestion = function(input) {
            var getNextWhenNoSelection = function(list) {
                return list.get(list.length - 1);
            }
            var getNext = $.fn.prev;
            _selectSuggestion(input, getNextWhenNoSelection, getNext);
        }

        var _selectSuggestion = function(suggestContext, getNextWhenNoSelection, getNext) {

            var suggestions = $(suggestContext.suggestBox).find("li");
            if (suggestions.length == 0) {
                return;
            }
            if ($(suggestContext.suggestBox).is(":hidden")) {
                //skip first select if the box is hidden
                if (suggestContext.options.bodyHideControlsClass && $(document.body).hasClass("ie6"))
                    $(document.body).addClass(suggestContext.options.bodyHideControlsClass);
                $(suggestContext.suggestBox).show();
                return;
            }
            var selectedSuggestion = suggestions.filter("." + options.itemSelectedClass);
            if (selectedSuggestion.length == 1) {
                var nextSugg = getNext.call(selectedSuggestion);
                selectedSuggestion.removeClass(options.itemSelectedClass);
                if (nextSugg.get(0) != undefined) {
                    setInputFromLi(suggestContext.input, nextSugg.get(0));
                    nextSugg.addClass(options.itemSelectedClass);
                }
                else {
                    suggestContext.input.value = suggestContext.previousInputValue;
                }
            }
            else {
                var nextSugg = getNextWhenNoSelection(suggestions);
                $(nextSugg).addClass(options.itemSelectedClass);
                setInputFromLi(suggestContext.input, nextSugg);
            }
        }

        var setInputFromLi = function(input, li) {
            input.value = unescapeHTML($(li).html());
        }

        var onKeyUp = function(event) {

            var suggestContext = event.data;

            if (suggestContext.disabled)
                return;

            var code = event.which;
            if (code == 27 || code == 38 || code == 40 || code == 13)//13 : RETURN
                return;

            if (suggestContext.previousInputValue && this.value == suggestContext.previousInputValue) {
                suggestContext.previousInputValue = this.value;
                return;
            }
            suggestContext.previousInputValue = this.value;
            displaySuggestions(suggestContext);
        }

        var onKeyDown = function(event) {

            var suggestContext = event.data;

            if (suggestContext.disabled)
                return;

            switch (event.which) {
                //ESC 
                case 27:
                    if (suggestContext.options.bodyHideControlsClass && $(document.body).hasClass("ie6"))
                        $(document.body).removeClass(suggestContext.options.bodyHideControlsClass);
                    $(suggestContext.suggestBox).hide();
                    break;
                //UP 
                case 38:
                    selectPreviousSuggestion(suggestContext);
                    break;
                //DOWN 
                case 40:
                    selectNextSuggestion(suggestContext);
                    break;
            }
        }


        return this.map(function() {

            if (this.nodeType != 1 || this.tagName != "INPUT" || this.type != "text")
                return;

            var suggestContext = {
                options: options,
                input: this,
                previousInputValue: null,
                suggestBox: null,
                suggestRequests: 0,
                suggestUpdate: 0,
                suggestions: [],
                inDelay: false,
                extractSuggestions: null,
                disabled: false,
                scope: "default",
                autoClosingTimer : null
            };

            switch (options.format) {
                case "google":
                    suggestContext.extractSuggestions = extractSuggestionsFromGoogleFormat;
                    break;
                default:
                    suggestContext.extractSuggestions = extractSuggestionsFromDefault;
                    break;
            }

            buildSuggestBox(suggestContext);

            $(this).attr("autocomplete", "off");
            $(this).bind("keyup", suggestContext, onKeyUp);
            $(this).bind("keydown", suggestContext, onKeyDown);

            return {
                off: function() {
                    $(suggestContext.suggestBox).hide();
                    if (suggestContext.options.bodyHideControlsClass && $(document.body).hasClass("ie6"))
                        $(document.body).removeClass(suggestContext.options.bodyHideControlsClass);
                    suggestContext.disabled = true;
                },
                on: function() {
                    suggestContext.disabled = false;
                }
            };
        })
    }
})(jQuery);

