﻿Cwo.RegisterNamespace("Cwo.AutoCompleteGeneric");

Cwo.AutoCompleteGeneric = function (ContainerID, TextBoxID, DropDownID, ButtonID, ServiceUrl, SearchItemPrefixURL, SearchItemAppendURL, WaterMarkCssClass, DemandEntryCssClass, ObjectImplementation, InstanceId, Data) {
    // private variables
    var genericautoComplete = this,
        watermarkCssClass = WaterMarkCssClass,
        demandEntryCssClass = DemandEntryCssClass,
        textbox = $("#" + TextBoxID),
        dropDown = $("#" + DropDownID),
        button = $("#" + ButtonID),
        dropDownID = DropDownID,
        serviceUrl = ServiceUrl,
        containerID = ContainerID,
        container = $("#" + containerID),
        backgroundElement = $("#" + ContainerID + " span"),
        instanceId = InstanceId,
        searchItemAppendURL = SearchItemAppendURL,
        searchItemPrefixURL = SearchItemPrefixURL,
        data = Data;

    genericautoComplete.Visible = false;
    ObjectImplementation.InstanceInformation.Textbox = textbox;
    ObjectImplementation.InstanceInformation.BaseObject = this;
    ObjectImplementation.InstanceInformation.Data = data;

    this.DropDownElementID = function () {
        return DropDownID;
    };

    this.SearchItemPrefixURL = function () {
        return searchItemPrefixURL;
    };

    this.EmptyDropDown = function () {
        dropDown.empty();
    };

    this.UpdateSearchItemPrefixURL = function (newPrefix) {
        // Save locally what the old prefix URL was; used for parsing through existing items (if any).
        var oldItemPrefixURL = searchItemPrefixURL, i = 0;

        searchItemPrefixURL = newPrefix;

        // Check if items already exist in the drop down; if so, update their prefix urls!
        if (dropDown[0] !== null && dropDown[0].childNodes !== null && dropDown[0].childNodes.length > 0) {
            // Drop down box does have items; handle them!
            for (i = 0; i < dropDown[0].childNodes.length; i += 1) {
                // Check if url is set.
                if (dropDown[0].childNodes[i].all[0] !== null) {
                    dropDown[0].childNodes[i].all[0].href = dropDown[0].childNodes[i].all[0].href.replace(oldItemPrefixURL, newPrefix);
                }
            }
        }
    };
    this.UpdateContainerCssClass = function (containerCssClass) {
        if (containerCssClass.length > 0) {
            container.removeClass();
            container.addClass(containerCssClass);
        }
    };
    function BindSearchType() {
        if (textbox.val() === "") {
            // Logic to see if we apply watermarkCssClass.
            if (watermarkCssClass.length > 0) {
                textbox.removeClass().addClass(watermarkCssClass);
            }
        }

        // Bind a new implementation to the click event.
        button.bind("click", function () {
            // Check if text empty.
            if (textbox.val().length > 0) {
                dropDown.empty();
                // Invoke the object implementation for search button click.
                ObjectImplementation.OverrideSearchClick();
            } else {
                // Empty textbox, check if demand entry css class has been applied.
                if (demandEntryCssClass.length > 0) {
                    textbox.removeClass().addClass(demandEntryCssClass);
                }
            }
        });
    }
    function MoveDown() {
        var selected = $("#" + dropDownID + " li.Selected");
        if (selected.size() > 0) {
            selected.next().addClass("Selected");
        } else {
            $("#" + dropDownID + " li:first").addClass("Selected");
        }

        selected.removeClass("Selected");
    }
    function MoveUp() {
        var selected = $("#" + dropDownID + " li.Selected");

        if (selected.size() > 0) {
            selected.prev().addClass("Selected");
        } else {
            $("#" + dropDownID + " li:last").addClass("Selected");
        }

        selected.removeClass("Selected");
    }
    this.Select = function () {
        var selected = $("#" + dropDownID + " li.Selected");

        if (selected.size() > 0) {
            textbox.val(selected.text());
            dropDown.empty();
        }

        // Check if text empty.
        if (textbox.val().length > 0) {
            dropDown.empty();
            // Invoke the object implementation for item select.
            ObjectImplementation.OverrideItemSelect();
        } else {
            // Empty textbox, check if demand entry css class has been applied.
            if (demandEntryCssClass.length > 0) {
                textbox.removeClass().addClass(demandEntryCssClass);
                textbox.addClass(demandEntryCssClass);
            }
        }
    };
    function Update() {
        // Update the DropDown
        var text = textbox.val(),
            isValid,
            AjajSequenceIndex = Cwo.Page.AjajCalls.CreateRequest("GenrcSearchSuggestion"),
            serviceData;

        if (text.length === 0) {
            dropDown.empty();

            if (genericautoComplete.Visible) {
                genericautoComplete.Visible = false;
                Cwo.Page.EventController.FireEvent("SearchPredictiveBox.VisibilityChange.Invisible");
            }
            textbox.removeClass().addClass(watermarkCssClass);
            return;
        }

        textbox.removeClass();
        //Remove illegal characters fron the text string, before the Ajax call and reset the textbox value
        text = genericautoComplete.RemoveIllegalCharacters(text);
        // Check that the characters are valid and remove leading whitespace
        isValid = genericautoComplete.ValidCharacterCheck(text, text.length);
        // Escape the text to allow single quotes
        text = text.replace(/['']/g, "\\'");
        // Get the Autocomplete results
        serviceData = "{\"FormValue\":\"" + text + "\"}";
        new Cwo.AjaxCall(serviceUrl, serviceData, function (Data) { genericautoComplete.Updated(Data, AjajSequenceIndex); }, null, null, true);
    }
    // public methods
    this.ForceUpdate = function (anchorElement) {
        textbox.val(anchorElement.innerText);
        genericautoComplete.Select();
    };
    this.KeyPressed = function (e) {
        // Check if it was a certain list of keys that was pressed
        var keyCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode,
        KEY = { UP: 38, DOWN: 40, DEL: 46, TAB: 9, RETURN: 13, ESC: 27, COMMA: 188, PAGEUP: 33, PAGEDOWN: 34, BACKSPACE: 8 };
        // Handle the Up/Down/Tab key events
        switch (keyCode) {
        case KEY.UP:
            MoveUp();
            break;
        case KEY.DOWN:
            MoveDown();
            break;
        case KEY.TAB:
            MoveDown();
            break;
        case KEY.RETURN:
            genericautoComplete.Select();
        break;
        case KEY.ESC:
            dropDown.empty();
            break;
        default:
            Update();
            break;
        }
        return;
    };
    this.Updated = function (data, AjajSequenceIndex) {
        if (Cwo.Page.AjajCalls.IsCurrentSequenceIndex("GenrcSearchSuggestion", AjajSequenceIndex)) {
            // Get the returned list
            var arr = data.d,
                textLen = textbox.val().length,
                item,
                placeName,
                highlight,
                itemHref;

            // Delete all the current items
            dropDown.empty();

            // Add new Items
            for (item in arr) {
                if (arr.hasOwnProperty(item)) {
                    placeName = arr[item];
                    highlight = "<em>" + placeName.substr(0, textLen) + "</em>" + placeName.substr(textLen, placeName.length - textLen);
                    itemHref = "";
                    // See if the item has a prefix URL for the href.
                    if (searchItemPrefixURL.toString().length > 1 && searchItemAppendURL.toString().length === 0) {
                        itemHref = " href=\"" + searchItemPrefixURL + placeName + "\" ";
                    } else if (searchItemPrefixURL.toString().length > 1 && searchItemAppendURL.toString().length > 1) {
                        itemHref = " href=\"" + searchItemPrefixURL + placeName + searchItemAppendURL + "\"";
                    } else if (searchItemPrefixURL.toString().length === 0 && searchItemAppendURL.toString().length > 1) {
                        itemHref = " href=\"" + placeName + searchItemAppendURL + "\"";
                    }

                    dropDown.append("<li><a onclick=\"return " + instanceId + ".ForceUpdate(this)\"" + itemHref + " title=\"" + placeName + "\">" + highlight + "</a></li>");
                }
            }

            if (!genericautoComplete.Visible) {
                genericautoComplete.Visible = true;
                Cwo.Page.EventController.FireEvent('SearchPredictiveBox.VisibilityChange.Visible');
            }

            // Add class to the last item
            $("#" + dropDownID + " li:last").addClass("Last");
        }
    };
    this.RemoveIllegalCharacters = function (text) {
        var removeBackslash = new RegExp("\\\\", "g");
        text = text.replace(removeBackslash, "");

        // Remove other illegal characters
        text = text.replace(/[#%*{}+@:<>""|?]/g, "");

        // Replace the ampersand with the text 'and'
        text = text.replace(/[&]/g, "and");

        return text;
    };
    this.ValidCharacterCheck = function (text, textlength) {
        var textAtPos = "",
            isValid = false, 
            i;

        // Check for a given number of characters that they are all valid. Handles multiple whitespace characters.
        for (i = 0; i < textlength; i += 1) {
            textAtPos = text.charAt(i);
            textAtPos = textAtPos.match("^[a-zA-Z0-9!()-,_;~]$") ? isValid = true : isValid = false;

            if (isValid === true) {
                return true;
            }
        }

        return isValid;
    };
    this.SetPlace = function (value) {
        textbox.val(value);
        if (textbox.val() === "") {
            backgroundElement.removeClass().addClass(watermarkCssClass);
        }
    };
    this.DemandEntry = function () {
        textbox.removeClass().addClass(demandEntryCssClass);
    };

    // bind the events
    $(document).ready(function () {
        Cwo.AutoCompleteGeneric.OnStart = function () {
            if ($.browser.opera) {
                textbox.bind("keypress", function (e) { genericautoComplete.KeyPressed(e); });
            } else {
                textbox.bind("keyup", function (e) { genericautoComplete.KeyPressed(e); });
            }

            textbox.focus(
                function () {
                    if (textbox.val() === "") {
                        textbox.removeClass();
                    }
                }
            ).blur(
                function () {
                    if (textbox.val() === "") {
                        textbox.removeClass().addClass(watermarkCssClass);
                    }
                }
            );

            // Makes the search box display the appropriate highlighting.
            BindSearchType();
        };

        // Exception handling code to log exceptions to the event viewer
        if (window.navigator.userAgent.indexOf("MSIE") > -1) {
            Cwo.AutoCompleteGeneric.OnStart();
            return;
        }

        try {
            Cwo.AutoCompleteGeneric.OnStart();
        } catch (ex) {
            Cwo.Error.TrackError(ex); // re-throw ex if error should propergate
        }
    });
};


