(function(searchForm) {
    searchForm.fn.rt_searchSuggest = function(args) {
        var formNode = $(this);
        var input = {minKeys:3, maxResults:5, inputId:""};
        var parameters = searchForm.extend(input, args);
        var text = $("#" + parameters.inputId);
        var keyCodes = {UP:38, PAGEUP:33, DOWN:40, PAGEDOWN:34, TAB:9, DEL:46, BACKSPACE:8, COMMA:188, ESC:27, RETURN:13};
        var query = null;
        var suggestions = null;
        var suggestionsCache = new Array();
        var selectedIndex = -1;
        var selectedSuggestion = null;
 if (false) { // TODO: enable after the push
        $(document.body).bind("click", function(event) {
            var hideSuggestions = true;
            var formId = formNode.attr("id");
            var parents = $(event.target).parents();
            for (var i = 0; i < parents.length; i++) {
                var parent = $(parents[i]);
                var parentId = $(parent).attr("id");
                if (formId == parentId) {
                    hideSuggestions = false;
                    break;
                }
            }
            if (hideSuggestions) {
                formNode.trigger("hideSuggestions");
            }
        });

        text.bind("focus", function(event) {
            selectedIndex = -1;
            formNode.trigger("showSuggestions");
        });

        text.bind("keyup.autocomplete", function(event) {
            query = text.attr("value");
            var length = query.length;

            // update the suggestions display...
            if (length >= parameters.minKeys) {
                var keyCode = event.keyCode;
                switch (keyCode) {
                    case keyCodes.DEL:
                        formNode.trigger("fetchSuggestions");
                        break;
                    case keyCodes.BACKSPACE:
                        formNode.trigger("fetchSuggestions");
                        break;
                    case keyCodes.COMMA:
                        formNode.trigger("fetchSuggestions");
                        break;
                    case keyCodes.ESC:
                        formNode.trigger("hideSuggestions");
                        break;
                    case keyCodes.RETURN:
                        if (selectedSuggestion != null) {
                            event.stopPropagation();
                            document.location = $($(selectedSuggestion).find("a").get(0)).attr("href");
                        } else {
                            formNode.submit();
                        }
                        return false;
                        break;
                    case keyCodes.UP:
                        formNode.trigger("selectPreviousSuggestion");
                        break;
                    case keyCodes.PAGEUP:
                        formNode.trigger("selectPreviousSuggestion");
                        break;
                    case keyCodes.DOWN:
                        formNode.trigger("selectNextSuggestion");
                        break;
                    case keyCodes.PAGEDOWN:
                        formNode.trigger("selectNextSuggestion");
                        break;
                    case keyCodes.TAB:
                        formNode.trigger("selectNextSuggestion");
                        break;
                    default:
                        formNode.trigger("fetchSuggestions");
                        break;
                }
            } else {
                formNode.trigger("hideSuggestions");
            }                                                     
        });

        formNode.bind("fetchSuggestions", function(event) {

            // check for cached suggestions...
            query = query.toLowerCase();
            if (query.length == parameters.minKeys) {
                suggestions = suggestionsCache[query];
            } else if (query.length > parameters.minKeys) {
                var cacheKey = query.substring(0, parameters.minKeys);
                var cachedSuggestions = suggestionsCache[cacheKey];
                if (cachedSuggestions) {
                    suggestions = new Array();
                    $.each(cachedSuggestions, function(i, suggestion) {
                        var type = suggestion.type;
                        if ("movie" == type) {
                            var title = suggestion.title.toLowerCase();
                            if (title.indexOf(query) != -1) {
                                suggestions[suggestions.length] = suggestion;
                            }
                        } else if ("actor" == type) {
                            var name = suggestion.name.toLowerCase();
                            if (name.indexOf(query) != -1) {
                                suggestions[suggestions.length] = suggestion;
                            }
                        }
                    });
                }
            }

            // load new suggestions if necessary...
            if (!suggestions || suggestions.length == 0) {
                suggestions = new Array();
                $.ajax({
                    type: "POST",
                    url: "/search/suggestion.php",
                    data: { query : query, count : parameters.maxResults * 2 },
                    dataType : "json",
                    success: function(response) {
                        suggestions = new Array();
                        $.each(response, function(i, suggestion) {
                            suggestions[i] = suggestion;
                        });
                        suggestionsCache[query] = suggestions;
                        formNode.trigger("showSuggestions");
                    }
                });
            } else {
                formNode.trigger("showSuggestions");
            }
            return suggestions;
        });

        formNode.bind("showSuggestions", function(event) {
            var movies = new Array();
            var actors = new Array();

            // organize the suggestions...
            $.each(suggestions, function(i, suggestion) {
                var type = suggestion.type;
                if (("movie" == type) && (movies.length <= parameters.maxResults)) {
                    movies[movies.length] = suggestion;
                } else if (("actor" == type) && (actors.length <= parameters.maxResults)) {
                    actors[actors.length] = suggestion;
                }
            });

            // populate the suggestions display...
            var searchSuggestions = '';
            if (movies.length > 0) {
                searchSuggestions += '<li class="header">Movies</li>';
                $.each(movies, function(i, movie) {
                    var title = movie.title;
                    searchSuggestions += '<li class="item">';
                    searchSuggestions += '  <div class="clearfix movie">';
                    searchSuggestions += '      <div class="icon"><img src="' + movie.poster.thumbnail + '"></div>';
                    searchSuggestions += '      <div class="name">';
                    searchSuggestions += '          <a href="' + movie.urls[0].url + '?lsrc=TypeAheadMovie">' + title + '</a>';
                    searchSuggestions += '          <div class="subtitle">' + movie.status + '</div>';
                    searchSuggestions += '      </div>';
                    searchSuggestions += '  </div>';
                    searchSuggestions += '</li>';
                });
                searchSuggestions += '<li class="moreResults">';
                searchSuggestions += '  <a class="hasNext" href="/search/full_search.php?lsrc=TypeAheadMovieResults&amp;search=' + query + '">View All Movie Results</a>';
                searchSuggestions += '</li>';
            }
            if (actors.length > 0) {
                searchSuggestions += '<li class="header">Celebrities</li>';
                $.each(actors, function(i, actor) {
                    var name = actor.name;                                                     
                    searchSuggestions += '<li class="item">';
                    searchSuggestions += '  <div class="clearfix actor">';
                    searchSuggestions += '      <div class="icon"><img src="' + actor.poster.thumbnail + '"></div>';
                    searchSuggestions += '      <div class="name">';
                    searchSuggestions += '          <a href="' + actor.urls[0].url + '?lsrc=TypeAheadCelebrity">' + name + '</a>';
                    searchSuggestions += '          <div class="subtitle">' + actor.type + '</div>';
                    searchSuggestions += '      </div>';
                    searchSuggestions += '  </div>';
                    searchSuggestions += '</li>';
                });
                searchSuggestions += '<li class="moreResults">';
                searchSuggestions += '  <a class="hasNext" href="/search/full_search.php?lsrc=TypeAheadCelebrityResults&amp;search=' + query + '">View All Celebrity Results</a>';
                searchSuggestions += '</li>';
            }
            
            var suggestionsDisplay = searchForm(".searchSuggestions");
            if (suggestionsDisplay.length) {
                suggestionsDisplay.show();
                suggestionsDisplay.html(searchSuggestions);
            } else {
                formNode.append('<ul class="searchSuggestions">' + searchSuggestions + '</ul>');
                suggestionsDisplay = searchForm(".searchSuggestions");
            }
            
            try {
                searchForm(".item").highlight(query);
            } catch(e) {
                /*do nothing*/
            }
            searchForm(".item").bind("mouseover", function(event) {
                selectedSuggestion = $(event.currentTarget);
                selectedIndex = searchForm(".item").index(selectedSuggestion);
                selectedSuggestion.addClass("selected");
            });
            searchForm(".item").bind("mouseout", function(event) {
                searchForm(".item").removeClass("selected");
            });
            searchForm(".item").bind("click", function(event) {
                document.location = $($(event.currentTarget).find("a").get(0)).attr("href");
            });
        });

        formNode.bind("hideSuggestions", function(event) {
            var suggestionsDisplay = searchForm(".searchSuggestions");
            if (suggestionsDisplay.length) {
                suggestionsDisplay.hide();
            }
            selectedSuggestion = null;
        });

        formNode.bind("selectNextSuggestion", function(event) {
            selectedIndex++;
            if (suggestions != null && selectedIndex >= searchForm(".item").length) {
                selectedIndex = 0;
            }
            selectSearchSuggestion();
        });
                                                                                                       
        formNode.bind("selectPreviousSuggestion", function(event) {
            selectedIndex--;
            if (suggestions != null && selectedIndex < 0) {
                selectedIndex = searchForm(".item").length - 1;
            }
            selectSearchSuggestion();
        });

        function selectSearchSuggestion() {
            searchForm(".item").removeClass("selected");
            selectedSuggestion = searchForm(".item").get(selectedIndex);
            if (selectedSuggestion) {
                $(selectedSuggestion).addClass("selected");
            }
        }

        return suggestions;
}
    };
})(jQuery);