﻿/// <reference path="../jquery-1.4.2-vsdoc.js" />

(function ($) {
    $.fn.intializeTypeAhead = function (options) {
        return this.each(function () {
            initialize($(this), options);
        });
    }

    $.getTypeAheadOptions = function () {
        return TypeAheadOptions;
    }

    $.expr[':'].textEquals = function (a, i, m) {
        return $(a).text().match("^" + m[3] + "$");
    };

    function initialize(textBox, options) {

        var acOptions = {
            minLength: options.minLength,
            delay: options.delay,
            source: options.source,
            selectFirst: options.selectFirst,
            open: function (event, ui) {
                var widget = $(this).autocomplete("widget");
                widget.find("ui-menu-item-alternate")
						.removeClass("ui-menu-item-alternate")
					.end()
					.find("li.ui-menu-item:odd")
						.addClass("ui-menu-item-alternate");
            },
            select: function (event, ui) {
                var item = ui.item;
                if (item.isReadOnly) {
                    return false;
                }
                options.itemSelected(item.data);
            }
        };
        textBox.click(function () { $(this).focus(); $(this).select(); });

        textBox.autocomplete(acOptions).data("autocomplete")._suggest = function (items) {
            if (!(textBox.hasFocus())) return false;

            var ul = this.menu.element.empty()
                                .zIndex(this.element.zIndex() + 1),
                        menuWidth,
                        textWidth;
            this._renderMenu(ul, items);

            this.menu.deactivate();
            this.menu.refresh();
            this.menu.element.show().position({
                my: "left top",
                at: "left bottom",
                of: this.element,
                collision: "none"
            });

            menuWidth = ul.width("").width();
            textWidth = this.element.width();

            var userWidth = (typeof options.width == "function") ? options.width(items) : options.width;
            ul.width(userWidth || Math.max(menuWidth, textWidth));

            var userHeight = (typeof options.height == "function") ? options.height(items) : options.height;
            ul.height(userHeight || ((items.length > 10) ? "10em" : "auto"));
        };

        textBox.autocomplete(acOptions)
			.addClass("ui-widget ui-widget-content")
			.unbind("blur.autocomplete")
			.data("autocomplete")._renderItem = function (ul, item) {
			    var listItem = $("<li></li>").data("item.autocomplete", item);
			    if (item.isReadOnly) {
			        listItem.addClass("ui-menu-item-label")
						.append(item.label);
			    }
			    else {
			        listItem.append("<a>" + options.formatItem(item) + "</a>")
			    }
			    return listItem.appendTo(ul);
			};

        textBox.keydown(function (e) {
            var keyCode = e.keyCode || e.which;
            if (keyCode >= 255) return;

            var availCodes = $.ui.keyCode;

            if (options.selectFirst) {
                if ((keyCode == availCodes.TAB || keyCode == availCodes.RETURN)) {
                    var autocomplete = $(this).data("autocomplete"),
						menu = autocomplete.menu;

                    if (!autocomplete.options.selectFirst) {
                        return;
                    }

                    var currentVal = $.trim(textBox.val());
                    var menuElement = menu.element;
                    var isNotSelected = autocomplete.selectedItem == null &&
									 menuElement.children().filter(function () {
									     return currentVal == $(this).text()
									 }).length == 0;

                    if (isNotSelected && menuElement.children().length > 0) {
                        menu.activate($.Event({ type: "mouseenter" }), menuElement.children().first());
                    }
                    return (keyCode == availCodes.TAB);
                }
            }
            else {
                if (keyCode == availCodes.TAB) {
                    textBox.autocomplete("close");
                }
            }
        });


        if (options.isComboBox) {
            textBox.addClass("ui-corner-left");
            $("<button>&nbsp;</button>")
				.attr("tabIndex", -1)
				.attr("title", "Show All Items")
				.insertAfter(textBox)
				.button({
				    icons: { primary: "ui-icon-triangle-1-s" },
				    text: false
				})
				.removeClass("ui-corner-all")
				.addClass("ui-corner-right ui-button-icon ui-autocomplete-button")
				.click(function () {
				    // close if already visible
				    if (textBox.autocomplete("widget").is(":visible")) {
				        textBox.autocomplete("close");
				        return false;
				    }
				    // close any other open typeaheads
				    $(".ui-autocomplete-input").filter(function () {
				        return $(this).autocomplete("widget").is(":visible");
				    }).autocomplete("close");

				    // pass empty string as value to search for, displaying all results
				    textBox.autocomplete("search", "");
				    textBox.focus();

				    return false;
				});
        }

        $("body:not(.ui-autocomplete)").live('click', function () {
            textBox.autocomplete("close");
        });
    }

    var TypeAheadOptions = {
        getTextHighlighter: function (searchTerm) {

            var highlightFunction = function (text) { return text; };
            if ($.trim(searchTerm) != "") {
                var re = $.ui.autocomplete.escapeRegex(searchTerm);
                var matcher = new RegExp("(" + re + ")", "gi");
                highlightFunction = function (text) {
                    return text.replace(matcher, "<span class='ta-highlight'>$1</span>");
                }
            }

            return {
                highlightSearchTerm: highlightFunction
            };
        },

        getDefaultClientOptions: function () {
            return TypeAheadOptions._baseClientOptions;
        },

        getDefaultServerOptions: function () {
            return TypeAheadOptions._baseServerOptions;
        },

        getCustomServerOptions: function (controllerName, actionName) {
            var serverOptions = {
                source: '/' + controllerName + '/' + actionName
            };

            return TypeAheadOptions.extendBaseServerOptions(serverOptions);
        },

        extendBaseServerOptions: function (customOptions) {
            var baseServerOptions = {
                minLength: 1,
                delay: 200,
                isComboBox: false,
                matchSubset: false,
                mustMatch: false,
                selectFirst: false,
                noDataMessage: "No matching items available.",
                formatItem: function (item) {
                    return item.label;
                },
                itemSelected: function (data) {

                },
                buildSourceUrlData: function () {
                    return {};
                },
                sourceUrl: "",
                parseItem: function (item, highlighter) {
                    return item;
                }
            };

            var updatedOptions = TypeAheadOptions._mergeObjects(baseServerOptions, customOptions);

            if (updatedOptions.parse == null) {
                updatedOptions.parse = function (data, request) {
                    var results = [];
                    var items = data.Items;
                    var highlighter = TypeAheadOptions.getTextHighlighter(request.term);
                    for (var i = 0; i < items.length; i++) {
                        results[results.length] = updatedOptions.parseItem(items[i], highlighter);
                    }
                    return results;
                }
            }

            updatedOptions.source = function (request, response) {

                var baseData = { term: request.term };
                var extendedData = updatedOptions.buildSourceUrlData();
                var sourceData = TypeAheadOptions._mergeObjects(baseData, extendedData);

                $.ajax({
                    url: updatedOptions.sourceUrl,
                    dataType: "json",
                    data: sourceData,
                    success: function (data) {
                        var results = [];

                        if (!(data.HasResults)) {
                            msg = updatedOptions.noDataMessage;
                        }
                        else {
                            results = updatedOptions.parse(data, request);

                            var msg = "";
                            if (data.MoreAvailable) {
                                msg = "More results available. Keep typing to refine search.";
                            }
                        }

                        if (msg != "") {
                            results[results.length] = {
                                data: {},
                                value: "",
                                label: msg,
                                isReadOnly: true
                            };
                        }
                        response(results);
                    }
                });
            };
            return updatedOptions;
        },

        extendBaseClientOptions: function (customOptions) {
            var baseClientOptions = {};
            return TypeAheadOptions._mergeObjects(baseClientOptions, customOptions);
        },

        addTypeAheadOptions: function (customOptions) {
            $.extend(TypeAheadOptions, customOptions);
        },

        _mergeObjects: function (baseObject, secondObject) {
            var merged = {};
            $.extend(merged, baseObject, secondObject);
            return merged;
        }
    }
})(jQuery);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
