$(document).ready(function() {
    var searchField = getSearchField();
    searchField.keyup(function(evt) {
        // Show suggestions whenever the search text has changed or the user hits the down arrow.
        if (evt.keyCode == 40 || isSearchFieldChanged(searchField)) {
            searchField.data('last', searchField.val());
            findSuggestions(searchField);
        }
    });

    // Hide the suggestions for any click in the document, except clicks in the search field.  Later we will also
    // exempt clicks in the suggestion area itself.
    $(document).click(function() {
        hidePopups(false);
    });
    searchField.click(function(evt) {
        evt.stopPropagation();
    });
});

function isSearchFieldChanged(searchField) {
    return searchField.data('last') != searchField.val();
}

function findSuggestions(searchField) {
    var searchText = searchField.val();
    if (searchText.match(/^(\w{2,}\s*)+$/) || searchText.match(/[^\w\s]+/)) {
        var params = {'q':searchText};
        var url = getSuggestionsUrl('suggest', params);
        $.get(url, function(data) {
            displaySuggestionHtml(searchField, data);
        });
    } else {
        hidePopups(false);
    }
}

function displaySuggestionHtml(searchField, html) {
    if (!isSearchFieldChanged(searchField)) {
        var suggestionsElt = getCleanSuggestionsElement();
        if (html.length > 0) {
            suggestionsElt.append(html);
            if (suggestionsElt.is(':hidden')) {
                showSuggestions();
            }
            suggestionsElt.attr('suggestfor', searchField.val());
        } else {
            hidePopups(false);
        }
    }                
}

function getCleanSuggestionsElement() {
    var suggestionsElt = $('#suggestions');
    suggestionsElt.data('selectionMode', 'keyboard');
    if (suggestionsElt.length == 0) {
        suggestionsElt = $('<div id="suggestions"></div>');
        $(getSearchForm()).after(suggestionsElt);
        addSuggestionHandlers(suggestionsElt);
    } else {
        suggestionsElt.empty();
    }

    var searchField = getSearchField();
    var width = searchField.outerWidth();
    suggestionsElt.width(width);
    return suggestionsElt;
}

function addSuggestionHandlers(suggestionsElt) {
    suggestionsElt.keydown(function(evt) {
        suggestionsElt.data('selectionMode','keyboard');
        return handleKeyDown(evt);
    });
    suggestionsElt.keyup(function(evt) {
        suggestionsElt.data('selectionMode','keyboard');
        if (evt.keyCode == 13) {
            handleSelection();
        }
    });
    suggestionsElt.mousemove(function() {
        suggestionsElt.data('selectionMode','mouse');
    });
    suggestionsElt.mouseover(function(evt) {
        if (suggestionsElt.data('selectionMode') === 'mouse') {
            selectFromMouseEvent(evt);
        }
    });
    suggestionsElt.click(function(evt) {
        evt.stopPropagation();
        selectFromMouseEvent(evt);
        handleSelection();
    });
}

function selectFromMouseEvent(evt) {
    var newSelection = $(evt.target).closest('.suggestion');
    if (!newSelection.hasClass('selected-suggestion')) {
        var oldSelection = $('.selected-suggestion');
        oldSelection.removeClass('selected-suggestion');
        newSelection.addClass('selected-suggestion');
    }
}

function showSuggestions() {
    var suggestionsElt = $('#suggestions');
    suggestionsElt.slideDown('fast');
    getSearchField().unbind('keydown.searchfield-suggestions');
    getSearchField().bind('keydown.searchfield-suggestions', function(evt) {
        return handleKeyDown(evt);
    });
}

function hidePopups(focusSearchField) {
    $('#suggestions').remove();
    var sf = getSearchField();
    sf.unbind('keydown.searchfield-suggestions');
    if (focusSearchField) {
        sf.get(0).focus();
    }

    var allCats = $('#all-categories');
    if (allCats.is(':visible')) {
        allCats.hide();
    }
    var allProds = $('#all-products');
    if (allProds.is(':visible')) {
        allProds.hide();
    }
}

function handleKeyDown(evt) {
    var key = evt.keyCode? evt.keyCode : evt.charCode;
    if (key == 40) {
        // Down arrow
        selectNextSuggestion();
        return false;
    } else if (key == 38) {
        // Up arrow
        selectPrevSuggestion();
        return false;
    } else if (key == 27) {
        // Escape
        hidePopups(true);
        return false;
    } else {
        return true;
    }
}

function handleSelection() {
    var selected = $('.selected-suggestion');
    if (selected.length > 0) {
        var selectedSuite = selected.attr('suite');
        if (selectedSuite != null && selectedSuite.length > 0) {
            reportSuggestion(selectedSuite, selected);
        }
        var action = selected.attr('action');
        eval(action);
    }
}

function selectNextSuggestion() {
    var newselection = getNextSelection();
    if (newselection != null && newselection.length > 0) {
        var oldselection = $('.selected-suggestion');
        changeSelection(oldselection, newselection);
    }
}

function getNextSelection() {
    var selected = $('.selected-suggestion');
    var newselection = null;
    if (selected.length > 0) {
        newselection = selected.nextAll('.suggestion:first');
        if (newselection.length == 0) {
            // We're at the end of a section, jump to the next.
            var area = selected.closest('.suggestionarea').nextAll('.suggestionarea:first');
            return area.children('.suggestion:first');
        } else {
            return newselection;
        }
    } else {
        return $('.suggestion:first');
    }
}

function selectPrevSuggestion() {
    var newselection = getPreviousSelection();
    var oldselection = $('.selected-suggestion');
    if (newselection != null && newselection.length > 0) {
        changeSelection(oldselection, newselection);
    } else {
        oldselection.removeClass('selected-suggestion');
        getSearchField().get(0).focus();
    }
}

function getPreviousSelection() {
    var selected = $('.selected-suggestion');
    var newselection = null;
    if (selected.length > 0) {
        newselection = selected.prevAll('.suggestion:first');
        if (newselection.length == 0) {
            // We're at the beginning of a selection, jump to the previous.
            var area = selected.closest('.suggestionarea').prevAll('.suggestionarea:first');
            return area.children('.suggestion:last');
        } else {
            return newselection;
        }
    } else {
        return null;
    }
}

function changeSelection(oldselection, newselection) {
    oldselection.removeClass('selected-suggestion');
    newselection.addClass('selected-suggestion');
    getSearchField().get(0).blur();
    newselection.get(0).focus();
}

function getSearchForm() {
    return document.forms['docsearch_form'];
}

function getSearchField() {
    var searchField = $('#docsearch');
    if (searchField.length == 0) {
        searchField = $('#searchfield');
    }
    return searchField;
}

function go(page) {
    document.location = page;
}

function more(q, type) {
    var divId = type + 'area';
    var div = $('#' + divId);
    div.css('minHeight', div.outerHeight());
    div.css('maxHeight', div.outerHeight());

    var moreElt = $('#more' + type);
    moreElt.removeClass('suggestmore');
    moreElt.removeClass('suggestion');
    moreElt.removeClass('selected-suggestion');
    moreElt.html('<img src="/help/search/img/progress.gif" style="position:relative;top:2px;left:5px;" />');
    var params = {'q':q, 'type':type, 'start':5};
    var url = getSuggestionsUrl('suggestmore', params);
    $.get(url, function(data) {
        moreElt.remove();
        displayMoreSuggestions(divId, data);
    });
}

function displayMoreSuggestions(divId, html) {
    $('#' + divId).append(html);
    $('.selected-suggestion').get(0).focus();
}

function search(q) {
    var sf = getSearchField();
    sf.val(q);
    var form = getSearchForm();
    $(form).trigger('submit');
    form.submit();
    hidePopups(false);
}

function getSuggestionsUrl(action, params) {
    var formAction = $('#docsearch_form').attr('action');
    params.width = getSearchField().width();
    return formAction.replace(/\/search(\/|$)/, '/search/' + action + '/') + '?' + $.param(params);
}

function reportSuggestion(suiteName, suggestionsElt) {
    try {
        var suggId = suggestionsElt.attr('id');
        var parts = suggId.split(':');
        var type = parts[0];
        var searchTerm = parts[2];
        var elt = suggestionsElt.get(0);
        var s = s_gi(suiteName);
        s.linkTrackVars='prop3,eVar3,events';
        s.linkTrackEvents='event35';
        s.eVar3=searchTerm + '::lucene::' + type;
        s.prop3=searchTerm + '::lucene::' + type;
        s.events='event35';
        s.tl(elt,'o','Doc Suggestion');
    } catch (e) {
        // Don't report the suggestion.
    }
}
