﻿(function ($, undefined) {
    $.fn.myautocomplete = function (opt) {
        return this.queue(function () {

            function init() {
                $("#autoprogress").hide();
                createautocomplete();
                addInput(0);
            }

            function createautocomplete() {
                holder = $('<ul class="holder"></ul>');
                element.after(holder);
                complete = $('<div class="facebook-auto">').append('<div class="default">' + options.complete_text + "</div>");
                complete.hover(function () { complete_hover = 0; }, function () { complete_hover = 1; });
                feed = $('<ul id="' + elemid + '_feed"></ul>');
                holder.after(complete.prepend(feed));
                feed.css("width", complete.width());
                elPrepare();
            }

            function elPrepare() {
                name = element.attr("name");
                if (options.bricket) {
                    if (name.indexOf("[]") == -1) {
                        name = name + "[]";
                    }
                }

                var temp_elem = $('<' + element.get(0).tagName + ' name="' + name + '" id="' + elemid + '" multiple="multiple" class="hidden">');
                $.each(element.children('option'), function (i, option) {
                    option = $(option);
                    temp_elem.data(option.val(), option.text());
                    if (option.hasClass("selected")) {
                        addItem(option.text(), option.val(), true, option.hasClass("locked"));
                        temp_elem.append('<option value="' + option.val() + '" selected="selected" class="selected">' + option.text() + '</option>');
                    }
                })
                element.after(temp_elem);
                element.remove();
                element = temp_elem;

                //public method to add new item
                $(element).bind("addItem", function (event, data) {
                    addItem(data.title, data.value, 0, 0, 0);
                });

                //public method to remove item
                $(element).bind("removeItem", function (event, data) {
                    var item = holder.children('li[rel=' + data.value + ']');
                    if (item.length) {
                        removeItem(item);
                    }
                });
            }

            //public method to remove item
            $(this).bind("destroy", function (event, data) {
                holder.remove();
                complete.remove();
                element.show();
            });

            function addItem(title, value, preadded, locked, focusme) {
                if (!maxItems()) {
                    return false;
                }
                var liclass = "bit-box" + (locked ? " locked" : "");
                var txt = document.createTextNode(title);
                var aclose = $('<a class="closebutton" href="#"></a>');
                var li = $('<li class="' + liclass + '" rel="' + value + '"></li>').prepend(txt).append(aclose);

                holder.append(li);

                aclose.click(function () {
                    removeItem($(this).parent("li"));
                    return false;
                });
                if (!preadded) {
                    $("#" + elemid + "_annoninput").remove();
                    addInput(focusme);
                    var _item = $('<option value="' + value + '" class="selected" selected="selected">' + title + '</option>').prop("selected", true);
                    element.append(_item);
                    if (options.onselect) {
                        funCall(options.onselect, _item);
                    }
                    element.change();
                }
                holder.children("li.bit-box.deleted").removeClass("deleted");
                feed.hide();
            }

            function removeItem(item) {
                if (!item.hasClass('locked')) {
                    item.fadeOut("fast");
                    if (options.onremove) {
                        var _item = element.children("option[value=" + item.attr("rel") + "]");
                        funCall(options.onremove, _item)
                    }
                    element.children('option[value="' + item.attr("rel") + '"]').remove();
                    item.remove();
                    element.change();
                    deleting = 0;
                }
            }


            function maxItems() {
                if (options.maxitems != 0) {
                    if (holder.children("li.bit-box").length < options.maxitems) {
                        return true;
                    } else {
                        return false;
                    }
                }
            }

            function addInput(focusme) {

                var li = $('<li class="bit-input" id="' + elemid + '_annoninput">');
                var input = $('<input type="text" class="maininput" size="1" autocomplete="off">');
                var getBoxTimeout = 0;

                holder.append(li.append(input));

                input.focus(function () {
                    if (maxItems()) {
                        complete.fadeIn("fast");
                    }
                });

                input.blur(function () {
                    if (complete_hover) {
                        complete.fadeOut("fast");
                    } else {
                        input.focus();
                    }
                });

                holder.click(function () {
                    input.focus();
                    if (feed.length && input.val().length) {
                        feed.show();
                    } else {
                        feed.hide();
                        complete.children(".default").show();
                    }
                });

                input.keypress(function (event) {
                    if (event.keyCode == 13) {
                        return false;
                    }
                    //auto expand input
                    input.attr("size", input.val().length + 1);
                });

                input.keydown(function (event) {
                    //prevent to enter some bad chars when input is empty
                    if (event.keyCode == 191) {
                        event.preventDefault();
                        return false;
                    }
                });


                input.keyup(function (event) {
                    var etext = xssPrevent(input.val());
                    if (event.keyCode == 8 && etext.length == 0) {
                        feed.hide();
                        if (holder.children("li.bit-box.deleted").length == 0) {
                            holder.children("li.bit-box:last").addClass("deleted");
                            return false;
                        }
                        else {
                            if (deleting) {
                                return;
                            }
                            deleting = 1;
                            holder.children("li.bit-box.deleted").fadeOut("fast", function () { removeItem($(this)); return false; });
                        }
                    }

                    if (event.keyCode != 40 && event.keyCode != 38 && event.keyCode != 37 && event.keyCode != 39 && etext.length >= 3) {
                        counter = 0;
                        if (options.json_url && maxItems()) {
                            getBoxTimeout++;
                            var getBoxTimeoutValue = getBoxTimeout;
                            $("#autoprogress").show();
                            $.ajax({
                                type: "POST",
                                data: "{keyword: '" + etext + "', gxExchangeUID: '" + options.gxexchangeuid + "', gxExchangeID: " + options.gxexchangeid + "}",
                                url: options.json_url,
                                contentType: "application/json",
                                dataType: "json",                                
                                success: function (response) {
                                    $("#autoprogress").hide();
                                    var data = eval(response.d)
                                    //alert(data);
                                    addMembers(etext, data);
                                    bindEvents();
                                },
                                error: function (xhr, status, error) {
                                    alert(status);
                                    // Display a generic error for now.
                                    //var err = eval("(" + xhr.responseText + ")");
                                    alert(xhr.responseText);
                                }
                            });

                        }

                        complete.children(".default").hide();
                        feed.show();
                    }
                });

                if (focusme) {
                    setTimeout(function () { input.focus(); complete.children(".default").show(); }, 1);
                }

            }

            function addMembers(etext, data) {
                feed.html('');

                var maximum = options.maxshownitems;
                var filter = "i";
                if (options.filter_case) {
                    filter = "";
                }

                var content = '';

                //addTextItem(etext);               

                $.each(data, function (i, object) {
                    content += '<li rel="' + object.key + '" title="' + object.ref + '">' + object.value + '</li>';
                    counter++;
                    maximum--;
                });

                feed.append(content);

                if (options.firstselected) {
                    focuson = feed.children("li:visible:first");
                    focuson.addClass("auto-focus");
                }

                //                if (counter > options.height) {
                //                    feed.css({
                //                        "height": (options.height * 24) + "px",
                //                        "overflow": "auto"
                //                    });
                //                } else {
                feed.css("height", "auto");
                //                }

                if (maxItems() && complete.is(':hidden')) {
                    complete.show();
                }
            }


            function bindEvents() {
                var maininput = $("#" + elemid + "_annoninput").children(".maininput");
                bindFeedEvent();
                feed.children("li").unbind("mousedown");
                feed.children("li").mousedown(function () {
                    var option = $(this);
                    addItem(option.text(), option.attr("rel"), 0, 0, 1);
                    feed.hide();
                    complete.hide();
                });
                maininput.unbind("keydown");
                maininput.keydown(function (event) {
                    if (event.keyCode == 191) {
                        event.preventDefault();
                        return false;
                    }

                    if (event.keyCode != 8) {
                        holder.children("li.bit-box.deleted").removeClass("deleted");
                    }

                    if ((event.keyCode == 13 || event.keyCode == 9) && checkFocusOn()) {
                        var option = focuson;
                        addItem(option.text(), option.attr("rel"), 0, 0, 1);
                        complete.hide();
                        event.preventDefault();
                        focuson = null;
                        return false;
                    }

                    if ((event.keyCode == 13 || event.keyCode == 9) && !checkFocusOn()) {
                        if (options.newel) {
                            var value = xssPrevent($(this).val());
                            addItem(value, value, 0, 0, 1);
                            complete.hide();
                            event.preventDefault();
                            focuson = null;
                            return false;
                        }

                        if (options.addontab) {
                            focuson = feed.children("li:visible:first");
                            var option = focuson;
                            addItem(option.text(), option.attr("rel"), 0, 0, 1);
                            complete.hide();
                            event.preventDefault();
                            focuson = null;
                            return false;
                        }
                    }

                    if (event.keyCode == 40) {
                        removeFeedEvent();
                        if (focuson == null || focuson.length == 0) {
                            focuson = feed.children("li:visible:first");
                            feed.get(0).scrollTop = 0;
                        } else {
                            focuson.removeClass("auto-focus");
                            focuson = focuson.nextAll("li:visible:first");
                            var prev = parseInt(focuson.prevAll("li:visible").length, 10);
                            var next = parseInt(focuson.nextAll("li:visible").length, 10);
                            if ((prev > Math.round(options.height / 2) || next <= Math.round(options.height / 2)) && typeof (focuson.get(0)) != "undefined") {
                                feed.get(0).scrollTop = parseInt(focuson.get(0).scrollHeight, 10) * (prev - Math.round(options.height / 2));
                            }
                        }
                        feed.children("li").removeClass("auto-focus");
                        focuson.addClass("auto-focus");
                    }
                    if (event.keyCode == 38) {
                        removeFeedEvent();
                        if (focuson == null || focuson.length == 0) {
                            focuson = feed.children("li:visible:last");
                            feed.get(0).scrollTop = parseInt(focuson.get(0).scrollHeight, 10) * (parseInt(feed.children("li:visible").length, 10) - Math.round(options.height / 2));
                        } else {
                            focuson.removeClass("auto-focus");
                            focuson = focuson.prevAll("li:visible:first");
                            var prev = parseInt(focuson.prevAll("li:visible").length, 10);
                            var next = parseInt(focuson.nextAll("li:visible").length, 10);
                            if ((next > Math.round(options.height / 2) || prev <= Math.round(options.height / 2)) && typeof (focuson.get(0)) != "undefined") {
                                feed.get(0).scrollTop = parseInt(focuson.get(0).scrollHeight, 10) * (prev - Math.round(options.height / 2));
                            }
                        }
                        feed.children("li").removeClass("auto-focus");
                        focuson.addClass("auto-focus");
                    }
                });
            }



            function bindFeedEvent() {
                feed.children("li").mouseover(function () {
                    feed.children("li").removeClass("auto-focus");
                    $(this).addClass("auto-focus");
                    focuson = $(this);
                });
                feed.children("li").mouseout(function () {
                    $(this).removeClass("auto-focus");
                    focuson = null;
                });
            }

            function removeFeedEvent() {
                feed.children("li").unbind("mouseover");
                feed.children("li").unbind("mouseout");
                feed.mousemove(function () {
                    bindFeedEvent();
                    feed.unbind("mousemove");
                });
            }

            function checkFocusOn() {
                if (focuson == null) {
                    return false;
                }
                if (focuson.length == 0) {
                    return false;
                }
                return true;
            }

            function xssPrevent(string) {
                string = string.replace(/[\"\'][\s]*javascript:(.*)[\"\']/g, "\"\"");
                string = string.replace(/script(.*)/g, "");
                string = string.replace(/eval\((.*)\)/g, "");
                string = string.replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '');
                return string;
            }

            var options = $.extend({
                json_url: null,
                cache: false,
                height: "10",
                newel: false,
                addontab: false,
                firstselected: false,
                filter_case: false,
                filter_selected: false,
                complete_text: "Start to type...",
                maxshownitems: 30,
                maxitems: 10,
                onselect: null,
                onremove: null,
                delay: 350,
                bricket: true,
                gxexchangeid: null,
                gxexchangeid: null
            }, opt);

            //system variables
            var holder = null;
            var feed = null;
            var complete = null;
            var counter = 0;

            var focuson = null;
            var deleting = 0;
            var complete_hover = 1;

            var element = $(this);
            var elemid = element.attr("id");

            init();

            return this;
        });
    };
})(jQuery);
