var isIE6=/MSIE 6/i.test(navigator.userAgent);
(function($) {
    var config;
    var delay;

    /**
     * HTML elements to use in creating suggestions.
     */
    var html = {
        CONTAINER: 'dl',
        SUGGESTION: 'dd',
        LABEL: 'label'
    }

    /**
     * Keycodes for handling keystrokes.
     */
    var keys = {
        UP: 38,
        DOWN: 40,
        DEL: 46,
        BACKSPACE: 8,
        TAB: 9,
        RETURN: 13,
        ESC: 27,
        PAGEUP: 33,
        PAGEDOWN: 34
    }

    /**
     * Creating the plugin.
     *
     * @param settings
     */
    $.fn.addQuerySuggestionService = function(settings) {
        config = {
			'serviceUrl': '/twigkit/services/query-suggestion-service/',
			'serviceId': 'static-completions',
			'serviceRemote': 'false',
			'action': '',
			'containerClassName': 'suggestions',
			'selectedClassName': 'selected'
		};

        if (settings) {
            $.extend(config, settings);
        }

        this.each(function() {
            attach(this);
        });

        return this;
    }

    /**
     * Bind the keyhandler to the INPUT elements.
     *
     * @param elem
     */
    function attach(elem) {
        $(elem).bind('keydown keyup', handleKeyPress);
    }

    /**
     * Handle each keypress within the INPUT element.
     *
     * @param event
     */
    function handleKeyPress(event) {
        // The INPUT element being targeted
        var input = event.target;

        // Getting the suggestions container if it exists
        var suggestionList = $('body').children(html.CONTAINER);

        // If the suggestions container does not exist then create it
        if (suggestionList.length == 0) {
            suggestionList = createContainer(input);
        }

        // If the INPUT loses focus, then hide any suggestion containers after a certain amount of time
        $(input).blur(function(event) {
            // Timeout is to allow for mouse clicks on a suggestion element
            setTimeout(function() {
				$(html.CONTAINER + "." + config.containerClassName).remove();
				if (!isIE6) $(input).removeClass('suggesting');
			}, 250);
        });

        // Clearing delay timer
        clearTimeout(delay);

        // Handling keystrokes
        switch (event.keyCode) {
            // Control keys
            case keys.UP:
                if (event.type == 'keydown') {
                    event.preventDefault();
                    changeSelection(suggestionList, keys.UP);
                }
                return false;

            case keys.DOWN:
                if (event.type == 'keydown') {
                    event.preventDefault();
                    changeSelection(suggestionList, keys.DOWN);
                }
                return false;

            case keys.RETURN:
                if (event.type == 'keydown' && suggestionList.children(html.SUGGESTION + '.' + config.selectedClassName).length > 0) {
                    event.preventDefault();
                    takeSelection(input, suggestionList);
                    suggestionList.remove();
					if (!isIE6) $(input).removeClass('suggesting');
                    return false;
                } else {
                    return true;
                }

            case keys.ESC:
                if (event.type == 'keydown') {
                    event.preventDefault();
                    suggestionList.remove();
					if (!isIE6) $(input).removeClass('suggesting');
                }
                return false;

            // Not a control key, so constructing a Query to the QuerySuggestionService
            default:
                if (event.type == 'keyup') {
                    delay = setTimeout(function() {
                    if (event.target.value.length > 0) {
                    	if (config.serviceRemote == 'true') {
							//var url = config.serviceUrl + '?q=' + event.target.value + '&serviceId=' + config.serviceId + '&callback=?';
							var url = config.serviceUrl + '?q=' + event.target.value + '&serviceId=' + $(input).attr('data-service-id') + '&callback=?';
						} else {
							var url = config.serviceUrl + config.serviceId + '/?q=' + event.target.value;
						}
                        $.ajax({
                            url: url,
							dataType: 'json',
                            success: function(data) {
                                suggestionList.empty();

                                // Add an HTML element for each suggestion
                                $.each(eval(data), function(i, suggestion) {
                                    createSuggestion(input, suggestion, suggestionList);
                                });

                                // Show the container if it has elements
                                if (suggestionList.children().length > 0) {
                                    suggestionList.show();
									if (!isIE6) $(input).addClass('suggesting');
                                } else {
									suggestionList.remove();
									if (!isIE6) $(input).removeClass('suggesting');
								}
                            }
                        });
                    }}, 100);//350
                }

                return true;
        }
    }

    /**
     * Creates the container to hold the suggestion elements.
     *
     * @param input
     */
    function createContainer(input) {
        var container = $(document.createElement(html.CONTAINER));
        container.addClass('suggestions labels');
        container.hide();
        container.css('top', $(input).offset().top + $(input).outerHeight() + 'px');
        container.css('left', $(input).offset().left + 'px');
        $('body').append(container);

        return container;
    }

    /**
     * Creates a single suggestion element.
     *
     * @param input
     * @param suggestion
     * @param suggestionList
     */
    function createSuggestion(input, suggestion, suggestionList) {
		config.action = $(input).parents('form').attr('action');

        suggestionElement = $(document.createElement(html.SUGGESTION));

        suggestionElement.attr('title', suggestion.value);
        suggestionElement.attr('rel', config.action+suggestion.parameters.replace(/&amp;/g, '&'));

        suggestionElement.html(suggestion.highlighting);

        var label = $(document.createElement(html.LABEL));
        label.html(suggestion.label);
        label.appendTo(suggestionElement);

        suggestionElement.appendTo($(suggestionList));

        suggestionElement.hover(function(event) {
            $(event.target).siblings().removeClass(config.selectedClassName);
            $(event.target).toggleClass(config.selectedClassName);
        });

        suggestionElement.bind('click', function(event) {
            $(event.target).addClass(config.selectedClassName);
            takeSelection(input, suggestionList);
        });
    }

    /**
     * Called when the user takes a given suggestion, either via keystroke or on mouse click.
     *
     * @param input
     * @param suggestionList
     */
    function takeSelection(input, suggestionList) {
        $(suggestionList).hide();
		if (!isIE6) $(input).removeClass('suggesting');

        $(input).val($(suggestionList).children(html.SUGGESTION + '.' + config.selectedClassName).attr('title'));
        //document.location = $(suggestionList).children(html.SUGGESTION + '.' + config.selectedClassName).attr('rel');
    }

    /**
     * Move between selection elements within the container.
     *
     * @param suggestionList
     * @param direction
     */
    function changeSelection(suggestionList, direction) {
        if ($(suggestionList).children(html.SUGGESTION + '.' + config.selectedClassName).length == 0) {
            // No element is selected
            $(suggestionList).children(html.SUGGESTION + ':' + (direction == keys.DOWN ? 'first' : 'last')).toggleClass(config.selectedClassName);
        } else {
            // A suggestion element is selected
            if (direction == keys.UP && $(suggestionList).children(html.SUGGESTION).eq(0).hasClass(config.selectedClassName)) {
                // If the top element is selected, and user clicks up arrow, then clear selections
                $(suggestionList).children(html.SUGGESTION).eq(0).removeClass(config.selectedClassName);
            } else {
                if (direction == keys.DOWN && $(suggestionList).children(html.SUGGESTION).eq($(suggestionList).children(html.SUGGESTION).length).hasClass(config.selectedClassName)) {
                    $(suggestionList).children(html.SUGGESTION).eq($(suggestionList).children(html.SUGGESTION).length).removeClass(config.selectedClassName);
                    $(suggestionList).children(html.SUGGESTION).eq(0).toggleClass(config.selectedClassName);
                } else {
                    var elem = $(suggestionList).children(html.SUGGESTION + '.' + config.selectedClassName);
                    elem.removeClass(config.selectedClassName);
                    if (direction == keys.UP) {
                        elem.prev().toggleClass(config.selectedClassName);
                    } else {
                        elem.next().toggleClass(config.selectedClassName);
                    }
                }
            }
        }
    }
})(jQuery);

$().ready(function() {
    $('input.suggest').each(function() {
        var settings = {};
        settings['serviceUrl'] = $(this).attr('data-service-url');
        settings['serviceId'] = $(this).attr('data-service-id');
        settings['serviceRemote'] = $(this).attr('data-service-remote');
        $(this).addQuerySuggestionService(settings);
    });
});

