var itemHiliteClass = "sugItemHiLite";
var itemUnhiliteClass = "sugItem";
var listClasName = "sug";

function trim(sInString) {
    // strip leading spaces
    sInString = sInString.replace(/^\s+/g, "");
    // strip trailing spaces
    return sInString.replace(/\s+$/g, "");
}

function SuggestionControl (textBox) {
    this.init (textBox);
}

SuggestionControl.prototype = {
    init: function(textBox) {
        textBox.setAttribute("autocomplete", "off");
        this.textBox = textBox;

        var x = findPosX(textBox);
        var y = findPosY(textBox);

        var div = document.createElement("div");
        div.className = "sugDiv";

        // display the div right below the textbox
        div.style.left = x + "px";
        div.style.top = y + textBox.offsetHeight + 1 + "px";
        div.style.zIndex = "1000";

        document.body.appendChild(div);
        this.div = div;

        this.datasource = "/global/SearchModule/citylookup.asp";
        this.paramName = "entry";

        attachEventListener(textBox, "keydown", handleKeyDown, true);
        attachEventListener(textBox, "keyup", handleKeyUp, true);

//        textBox.onblur = function() {this.suggestionBox.disabled = true;};
//        textBox.onfocus = function() {this.suggestionBox.disabled = false;};

        // create a hidden iframe to fix the IE select control z-index problem
        var divBG = document.createElement("iframe");
        divBG.setAttribute("src", "/images/pixel_invisible.gif");
        divBG.setAttribute("scrolling", "no");
        divBG.setAttribute("frameborder", "0");
        divBG.style.position = "absolute";
        divBG.style.display = "none";
        divBG.style.visibility = "hidden";
        divBG.style.left = div.style.left;
        divBG.style.top = div.style.top;
        divBG.style.zIndex = "999";
        div.parentNode.appendChild(divBG);
        this.divBG = divBG;

        this.hilitedItem = null;

        // define functions
        this.sDepArr    = "XX";
        this.searchType = "XX";
        this.textBox.enterKeyPressed = false;
        this.disabled = false;
    },

    show: function() {
        var x = findPosX(this.textBox);
        var y = findPosY(this.textBox);

        // display the div right below the textbox
        this.div.style.left = x + "px";
        this.div.style.top = y + this.textBox.offsetHeight + 1 + "px";
        this.divBG.style.left = this.div.style.left;
        this.divBG.style.top = this.div.style.top;

        this.div.style.visibility = "visible";
        this.div.style.display = "block";
        this.divBG.style.display = "block";
        this.divBG.style.visibility = "visible";
        this.divBG.style.width = this.div.offsetWidth + "px";
        this.divBG.style.height = this.div.offsetHeight + "px";
    },

    hide: function() {
        this.div.style.visibility = "hidden";
        this.div.style.display = "none";
        this.div.innerHTML = "";
        this.hilitedItem = null;
        this.divBG.style.visibility = "hidden";
        this.divBG.style.display = "none";
        this.clearTimer();
    },

    selectItem: function(item) {
        this.textBox.value = item.value;

        if (this.cityNameField) {
            this.cityNameField.value = this.hilitedItem.city;
        }

        // blank out state codes that have 0
        // this is for foreign cities

        if (this.stateCodeField) {
            if (this.hilitedItem.stateCode == '0') {
                 this.stateCodeField.value = "";
            } else {
                this.stateCodeField.value = this.hilitedItem.stateCode;
            }
        }

        if (this.countryCodeField) {
            this.countryCodeField.value = this.hilitedItem.countryCode;
        }

        if (this.airportCodeField) {
            this.airportCodeField.value = this.hilitedItem.airportCode;
        }

        this.hide();
    },

    hiliteItem: function(item) {
        if (item.container.hilitedItem != null) {
            this.unhiliteItem(this.hilitedItem);
        }

        item.className = itemHiliteClass;
        this.hilitedItem = item;
    },

    unhiliteItem: function(item) {
        item.className = itemUnhiliteClass;
    },

    initItem: function(item) {
        var container = this;
        item.container = container;
        item.onmouseover = function() {
            container.hiliteItem(item);
        };
        item.onmouseout = function() {
            container.unhiliteItem(item);
        };
        item.onfocus = function() {
            container.hiliteItem(item);
        };
        item.onblur = function() {
            container.unhiliteItem(item);
        };
        item.onclick = function() {
            container.hilitedItem = item;
            container.selectItem(item);
        };
    },

    initItems: function() {
        this.items = this.div.getElementsByTagName("input");

        // build a linked list for easy navigation
        for (var i = 0; i < this.items.length; i++) {
            if (this.items.length == 1) {
                this.items[i].prev = this.items[0];
                this.items[i].next = this.items[0];
            } else if (i == 0) {
                this.items[i].prev = this.items[this.items.length - 1];
                this.items[i].next = this.items[i + 1];
            } else if (i == this.items.length - 1) {
                this.items[i].prev = this.items[i - 1];
                this.items[i].next = this.items[0];
            } else {
                this.items[i].prev = this.items[i - 1];
                this.items[i].next = this.items[i + 1];
            }
            this.initItem(this.items[i]);
        }
    },

    showData: function(text) {
        this.div.innerHTML = "";

        // converting xml into html
        var ul = document.createElement("ul");
        ul.className = listClasName;

        // text is in json format
        var data = eval('(' + text + ')');

        var suggestions = data.locations;
        for (var i = 0; i < suggestions.length; i++) {
            var li = document.createElement("li");
            var input = document.createElement("input");
            input.type = "button";
            input.city = suggestions[i].city;
            input.stateCode = suggestions[i].stateCode;
            input.countryCode = suggestions[i].countryCode;
            input.airportCode = suggestions[i].airportCode;
            input.value = suggestions[i].text;
            input.className = itemUnhiliteClass;
            li.appendChild(input);
            ul.appendChild(li);
        }

        this.div.appendChild(ul);
        this.initItems();

        var itemCount = this.items.length;

        if (itemCount > 0) {

            this.show();

            // adjust the width of the item
            var maxItemWidth = 0;

            // find out the maximum width of the suggestion items
            for (var i = 0; i < itemCount; i++) {
                var itemWidth = this.items[i].offsetWidth;
                if (itemWidth > maxItemWidth) {
                    maxItemWidth = itemWidth;
                }
            }

            for (var i = 0; i < this.items.length; i++) {
                this.items[i].style.width = maxItemWidth;
            }

            this.hiliteItem(this.items[0]);

        } else {
            this.hide();
        }
    },

    disable: function() {
        this.disabled = true;
    },

    // The timer function allows us to get the data
    // from the server at a pre-determined interval
    // in order to reduce network traffic. If the
    // user has entered something really fast, then
    // only the last entry will generate a call to
    // the server. This will allow us to conserve
    // server resources without compromising user
    // performance
    initTimer: function() {
        var sb = this;
        var f = function() {
            getDataFromServer(sb);
        };
        this.timerProcess = setInterval(f, 500);
    },

    clearTimer: function() {
        if (this.timerProcess) {
            clearInterval(this.timerProcess);
            this.timerProcess = null;
        }
    },

    isVisible: function() {
        return this.div.style.visibility == 'visible';
    }
};

function getDataFromServer(sb) {
    var xmlHttp = getReq();
    var userEntry = trim(sb.textBox.value);

    if ((userEntry.length == 2) && 
        (sb.textBox.value.length == 3) && 
        (sb.textBox.value.substring(2,3) == " "))
    {
      userEntry = sb.textBox.value;
    }

    if (userEntry.length < 3 || userEntry == sb.lastEntry || sb.disabled) {
        return;
    }

    var userEntryToSend = userEntry;
    if ((userEntry.substring(0,3).toUpperCase() == "FT ") ||
        (userEntry.substring(0,3).toUpperCase() == "FT."))
    {
      userEntryToSend = "Fort " + userEntry.substring(3,userEntry.length);
    }

    if ((userEntry.substring(0,3).toUpperCase() == "MT ") ||
        (userEntry.substring(0,3).toUpperCase() == "MT."))
    {
      userEntryToSend = "Mount " + userEntry.substring(3,userEntry.length);
    }

    if ((userEntry.substring(0,3).toUpperCase() == "ST ") ||
        (userEntry.substring(0,3).toUpperCase() == "ST."))
    {
      userEntryToSend = "Saint " + userEntry.substring(3,userEntry.length);
    }

    var url = sb.datasource + "?" + sb.paramName + "=" + userEntryToSend + "&DEPARR=" + sb.sDepArr + "&searchType=" + sb.searchType ;
    xmlHttp.open('GET', url, true);

    var tb = this.textBox;

    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState != 4) {
            return;
        }

        if (!sb.disabled) {
            sb.showData(xmlHttp.responseText);
        }
    };
    sb.lastEntry = userEntry;
    xmlHttp.send(null);
}

function enableSuggestion(textBox) {
    textBox.enterKeyPressed = false;
    textBox.suggestionBox = new SuggestionControl(textBox);
}

function getKeyCode(e) {
    if (window.event) {
        return window.event.keyCode;
    } else if (e) {
        return e.which;
    } else {
        return null;
    }
}

var KEY = {
    UPARROW: 38,
    DOWNARROW: 40,
    LEFTARROW: 37,
    RIGHTARROW: 39,
    ESC:27,
    HOME: 36,
    END: 35,
    ENTER: 13,
    BKSPACE: 8,
    DELETE: 46,
    TAB: 9,
    SHIFT: 16,
    isNavigationKey: function(keyCode) {
        switch (keyCode) {
            case KEY.UPARROW:
            case KEY.LEFTARROW:
            case KEY.DOWNARROW:
            case KEY.RIGHTARROW:
            case KEY.HOME:
            case KEY.END:
                return true;
        }
        return false;
    },
    isCharKey: function isCharKeyPressed(keyCode) {
        // A thru Z
        if (keyCode >= 65 && keyCode <= 90) {
            return true;
        }

        if (keyCode == 32)
        {
          return true;
        }

        // a thru z
        if (keyCode >= 97 && keyCode <= 122) {
            return true;
        }

        // 0 thru 9
        if (keyCode >= 48 && keyCode <= 57) {
            return true;
        }

        if (keyCode >= 187 && keyCode <= 191) {
            return true;
        }

        return false;
    }
};

function handleNavigationKeys(event) {

    var target = getEventTarget(event);
    var suggestionBox;

    // this event handler could be attached to either the text box or suggestion item
    if (target.type == 'text') {
        suggestionBox = target.suggestionBox;
    } else {
        suggestionBox = target.textBox.suggestionBox;
    }

    if (!suggestionBox.isVisible()) {
        return true;
    }

    if (suggestionBox.hilitedItem == null) {
        return false;
    }

    var items = suggestionBox.items;
    var keyCode = getKeyCode(event);

    switch (keyCode) {
        case KEY.UPARROW:
        case KEY.LEFTARROW:
            suggestionBox.hiliteItem(suggestionBox.hilitedItem.prev);
            break;
        case KEY.DOWNARROW:
        case KEY.RIGHTARROW:
            suggestionBox.hiliteItem(suggestionBox.hilitedItem.next);
            break;
        case KEY.HOME:
            suggestionBox.hiliteItem(items[0]);
            break;
        case KEY.END:
            suggestionBox.hiliteItem(items[items.length - 1]);
            break;
    }
    return false;
}

function handleKeyDown(event) {
    var textBox = getEventTarget(event);
    var keyCode = getKeyCode(event);

    if (textBox.suggestionBox.isVisible()) {
        switch (keyCode) {
            case KEY.ENTER:
                textBox.suggestionBox.selectItem(textBox.suggestionBox.hilitedItem);
                preventDefault(event);
                textBox.enterKeyPressed = true;
                stopEvent(event);
                return false;
            case KEY.DELETE:
                clearFields(textBox);
                return true;
            case KEY.ESC:
                textBox.suggestionBox.hide();
                clearFields(textBox);
                return false;
            case KEY.TAB:
                clearFields(textBox);
                if (textBox.suggestionBox.isVisible()) {
                    textBox.suggestionBox.hide();
                }
                return true;
        }
    }
    return true;
}

function clearFields(textBox) {
    if (textBox.suggestionBox.cityNameField) {
        textBox.suggestionBox.cityNameField.value = "";
    }
    if (textBox.suggestionBox.stateCodeField) {
        textBox.suggestionBox.stateCodeField.value = "";
    }
    if (textBox.suggestionBox.countryCodeField) {
        textBox.suggestionBox.countryCodeField.value = "";
    }
    if (textBox.suggestionBox.airportCodeField) {
        textBox.suggestionBox.airportCodeField.value = "";
    }
}

function handleKeyUp(event) {
    var textBox = getEventTarget(event);

    if (textBox.suggestionBox.disabled) {
        return false;
    }

    var userEntry = trim(textBox.value);
    if ((userEntry.length == 2) && 
        (textBox.value.length == 3) && 
       (textBox.value.substring(2,3) == " "))
    {
      userEntry = textBox.value;
    }

    var keyCode = getKeyCode(event);

    if (KEY.isCharKey(keyCode)) {
        textBox.enterKeyPressed = false;
        clearFields(textBox);
    }

    switch (keyCode) {
        case KEY.ENTER:
            return false;
        case KEY.ESC:
            return false;
        case KEY.BKSPACE:
        case KEY.DELETE:
            textBox.suggestionBox.lastEntry = "";
            textBox.enterKeyPressed = false;
    }

    if (userEntry.length >= 3) {

        if (textBox.suggestionBox.isVisible()) {

            if (KEY.isNavigationKey(keyCode)) {
                return handleNavigationKeys(event);
            }
        }

        // start the time only if is not started yet
        if (!textBox.suggestionBox.timerProcess) {
            textBox.suggestionBox.initTimer();
        }
    } else {
        textBox.suggestionBox.hide();
    }
    return true;
}