/*
  @author: Zach Borboa / http://zachborboa.com
  @url: http://darklaunch.com/creating-an-autosuggest-with-javascript
  @usage: $("#input").jAutoSuggest(options);
  @params:
    url - optional url to get suggestions; defaults to Google's query suggestions
    delay - optional sets the delay between keyup and the ajax request; defaults to zero delay
  @license: Creative Commons License - ShareAlike http://creativecommons.org/licenses/by-sa/3.0/
  @version: 1.0
  @changes: 
*/

;(function($){
    $.fn.jAutoSuggest = function(options){
        
        var defaults = {
            url        : "http://clients1.google.com/complete/search?client=hp&q=",
            target     : "#q",
            dataType   : "jsonp",
            method     : "GET",
            delay      : 300,
            cache      : false,
            async      : true,
            beforeSend : false,
            complete   : false,
            error      : false
        };
        
        var options = $.extend(defaults, options);
        
        return this.each(function(){
            var elm = $(this);
            var query = "";
            var originalQuery = "";
            var currentIndex = "";
            var searchTimeout = "";
            
            function init() {
                $("#autosuggest").html("");
                disableAutocomplete();
                bindKeys();
                bindResults();
            }
            
            function bindKeys() {
                elm.keydown(function(e) {
                    switch (e.which) {
                        case 40: { // down
                            if (!resultsShown()) {
                                query = $(options.target).val();
                                if (!(query == "")) {
                                    showResults();
                                }
                            }
                            else {
                                // down pressed when last result focused
                                if (currentIndex === $("#autosuggest li").length - 1) {
                                    currentIndex = "";
                                    clearHighlights();
                                    setSearchField(originalQuery);
                                }
                                // down pressed when input field focused
                                else if (currentIndex === "") {
                                    currentIndex = 0;
                                    focusResult();
                                }
                                // down pressed when result focused
                                else {
                                    currentIndex++;
                                    focusResult();
                                }
                            }
                            break;
                        }
                        case 38: { // up
                            if (!resultsShown()) {
                                showResults();
                            }
                            else {
                                // up pressed when input field focused
                                if (currentIndex === "") {
                                    currentIndex = $("#autosuggest li").length - 1;
                                    focusResult();
                                }
                                // up pressed when first result focused
                                else if (currentIndex === 0) {
                                    currentIndex = "";
                                    clearHighlights();
                                    setSearchField(originalQuery);
                                }
                                // up pressed when result focused
                                else {
                                    currentIndex--;
                                    focusResult();
                                }
                            }
                            break;
                        }
                        case 13: { // return
                            query = $(options.target).val();
                            hideResults();
                            submitSearch();
                            break;
                        }
                        case 27: { // escape
                            setSearchField(originalQuery);
                            hideResults();
                            break;
                        }
                        case  9:   // tab
                        case 33:   // page up
                        case 34:   // page down
                        case 37:   // left
                        case 39: { // right
                            break;
                        }
                        default: {
                            clearTimeout(searchTimeout);
                            searchTimeout = setTimeout(search, 300);
                            break;
                        }
                    }
                });
                
                elm.blur(function() {
                    hideResults();
                });
                
                elm.focus(function() {
                    disableAutocomplete();
                });
            }
            
            function bindResults() {
                $("#autosuggest li").bind({
                    mouseover: function(){
                        currentIndex = $(this).index();
                        clearHighlights();
                        highlightResult(currentIndex);
                    },
                    mousedown: function(){
                        currentIndex = $(this).index();
                        query = $("#autosuggest li").eq(currentIndex).text();
                        setSearchField(query);
                        submitSearch();
                    }
                });
            }
            
            function focusResult() {
                clearHighlights();
                highlightResult();
                query = $("#autosuggest li").eq(currentIndex).text();
                setSearchField(query);
            }
            
            function highlightResult() {
                $("#autosuggest li").eq(currentIndex).addClass("active");
            }
            
            function setResultWidth() {
                $("#autosuggest").css({"width": $(options.target).width() + 4});
            }
            
            function clearHighlights() {
                $("#autosuggest li").removeClass("active");
            }
            
            function resultsShown() {
                return $("#autosuggest").is(":visible");
            }
            
            function search(text) {
                query = $(options.target).val();
                if (!(query == originalQuery || query == "")) {
                    originalQuery = query = $(options.target).val();
                    $.ajax({
                        type : options.method,
                        url : options.url + escape(query),
                        dataType : options.dataType,
                        cache : options.cache,
                        async : options.async,
                        beforeSend : function(){
                            if (options.beforeSend) {
                                options.beforeSend();
                            }
                        },
                        complete : function(XMLHttpReq, textStatus) {
                            if (options.complete) {
                                options.complete(XMLHttpReq, textStatus);
                            }
                        },
                        success : function(data) {
                            var response = data["1"];
                            var lis = "";
                            for (i in response) {
                                var r = response[i]["0"];
                                lis += "<li>" + r + "</li>";
                            }
                            if (!($("#autosuggest").length == 1)) {
                                $(options.target).parent("form").after("<ul id=\"autosuggest\"><li></li></ul>");
                            }
                            $("#autosuggest").html(lis);
                            currentIndex = "";
                            clearHighlights();
                            bindResults();
                            showResults();
                        },
                        error : function (event, request, settings) {
                            if (options.error) {
                                options.error(event, request, settings);
                            }
                        }
                    });
                }
            }
            
            function setSearchField(text) {
                $(options.target).val(text);
            }
            
            function disableAutocomplete() {
                //~ document.getElementById($(options.target).attr("id")).setAttribute("autocomplete", "off");
                $(options.target).get(0).setAttribute("autocomplete", "off");
            }
            
            function showResults() {
                setResultWidth();
                if (!($("#autosuggest").html() == "")) {
                    $("#autosuggest").show();
                }
            }
            
            function hideResults() {
                $("#autosuggest").hide();
            }
            
            function submitSearch() {
                $(options.target).parent("form").submit();
            }
            
            init();
        });
    };
})(jQuery);