var iAPPSFormPrefix = "iAPPSForm_";
var iAPPSFormClass = "iAPPSForm";
var iAPPSFormZIndex = 500;

function iAPPSForm_Initialize() {
    if (!($.browser.msie && $.browser.version < 7)) {
        $("input." + iAPPSFormClass + ":text").each(function () {
            var controlId = $(this).attr("id");
            if (controlId != null && controlId != "" && !(window[controlId] instanceof iAPPSForm_TextBox)) {
                window[controlId] = new iAPPSForm_TextBox(this);
            }
        });
        $("TextArea." + iAPPSFormClass).each(function () {
            var controlId = $(this).attr("id");
            if (controlId != null && controlId != "" && !(window[controlId] instanceof iAPPSForm_TextArea)) {
                window[controlId] = new iAPPSForm_TextArea(this);
            }
        });
        $("select." + iAPPSFormClass).each(function () {
            var controlId = $(this).attr("id");
            if (controlId != null && controlId != "" && !(window[controlId] instanceof iAPPSForm_SelectBox)) {
                window[controlId] = new iAPPSForm_SelectBox(this);
            }
        });
    }
}

function iAPPSForm_SelectBox(formElement) {
    /**************
    * Properties *
    **************/

    this.ControlId = $(formElement).attr("id");
    this.Control = formElement;
    this.FormElement;
    this.InTransition = false;
    this.IsExpanded = false;
    this.IsVisible = true;

    /**********
    * Methods *
    ***********/

    // Displays the rendered control on the page
    this.Show = function () {
        this.IsVisible = true;

        $(this.FormElement).show();
    }

    // Hides the rendered control on the page
    this.Hide = function () {
        this.IsVisible = false;

        $(this.FormElement).hide();
    }

    // Toggles the visibility of the rendered control on the page
    this.Toggle = function () {
        if (this.IsVisible) {
            this.Hide();
        }
        else {
            this.Show();
        }
    }

    // Returns the selected value of the select element
    this.GetSelectedValue = function () {
        return $(this.Control).children("option:selected").val();
    }

    // Returns the selected index of the select element
    this.GetSelectedIndex = function () {
        var iAPPSSelectedItem = $(this.Control).children("option:selected");

        return $(this.Control).children("option").index(iAPPSSelectedItem);
    }

    // Sets the selected index of the select element and rebinds to custom control
    this.SetSelectedIndex = function (newIndex, doOnChange) {
        var currentIndex = this.GetSelectedIndex();

        if (newIndex != currentIndex) {
            $(this.Control).children("option:eq(" + newIndex + ")").attr("selected", "selected");

            if (typeof (doOnChange) == "boolean" && doOnChange) {
                if (typeof (this.Control.onchange) == "function") {
                    this.Control.onchange();
                }
            }

            this.RenderListItems();
        }
    }

    // Generates default custom styles if they have not already been rendered
    this.RenderStyles = function () {
        if ($("style#iAPPSFormSelectBox").size() == 0) {
            var iAPPSFormStyles = "";

            iAPPSFormStyles += "<style id=\"iAPPSFormSelectBox\" type=\"text/css\">";
            iAPPSFormStyles += "div.iAPPSFormSelectBox {position: relative; float: left; outline: none; cursor: default; text-align: left !important;}";
            iAPPSFormStyles += "div.iAPPSFormSelectBox div.selectedOption span {display: block; overflow: hidden; white-space: nowrap;}";
            iAPPSFormStyles += "div.iAPPSFormSelectBox div.options {display: none;}";
            iAPPSFormStyles += "div.iAPPSFormSelectBox.expanded div.options {display: block;}";
            iAPPSFormStyles += "div.iAPPSFormSelectBox div.options ul {max-height: 250px; margin: 0; padding: 0; overflow: auto; list-style-type: none;}";
            iAPPSFormStyles += "div.iAPPSFormSelectBox div.options div.selectFooter {float: left;}";
            iAPPSFormStyles += "</style>";

            $("head").append(iAPPSFormStyles);
        }
    }

    // Generates HTML and binds event handlers to custom control
    this.RenderControl = function () {
        if (typeof (this.FormElement) == "undefined") {
            var iAPPSFormElement = "";

            var iAPPSInlineStyle = typeof ($(this.Control).attr("style")) != "undefined" ? $(this.Control).attr("style") : "";

            iAPPSFormElement += "<div id=\"" + iAPPSFormPrefix + this.ControlId + "\" class=\"" + $(this.Control).attr("class") + "\" style=\"" + iAPPSInlineStyle + "\">";
            iAPPSFormElement += "<div class=\"selectHeader\">";
            iAPPSFormElement += "<div class=\"selectedOption\">";
            iAPPSFormElement += "<span></span>";
            iAPPSFormElement += "</div>";
            iAPPSFormElement += "</div>";
            iAPPSFormElement += "<div class=\"options\">";
            iAPPSFormElement += "<ul></ul>";
            iAPPSFormElement += "<div class=\"selectFooter\">";
            iAPPSFormElement += "<div></div>";
            iAPPSFormElement += "</div>";
            iAPPSFormElement += "</div>";
            iAPPSFormElement += "</div>";

            $(this.Control).after(iAPPSFormElement);

            this.FormElement = $("div#" + iAPPSFormPrefix + this.ControlId)[0];

            $(this.FormElement).attr("tabindex", 0).addClass("iAPPSFormSelectBox").removeClass(iAPPSFormClass).css;

            $(this.Control).hide();

            // Focus Handler
            $(this.FormElement).bind("focus", { "iAPPSFormElement": this }, function (event) {
                var iAPPSFormElement = event.data.iAPPSFormElement;

                $(iAPPSFormElement.FormElement).css("z-index", iAPPSFormZIndex);
                $(iAPPSFormElement.FormElement).addClass("focused");
            });

            // Blur Handler
            $(this.FormElement).bind("blur", { "iAPPSFormElement": this }, function (event) {
                var iAPPSFormElement = event.data.iAPPSFormElement;

                if ($(iAPPSFormElement.FormElement).hasClass("expanded")) {
                    iAPPSFormElement.InTransition = true;

                    window[iAPPSFormElement.ControlId + "_Blur"] = setTimeout(function () {
                        iAPPSFormElement.InTransition = false;
                        $(iAPPSFormElement.FormElement).removeClass("expanded");
                        $(iAPPSFormElement.FormElement).removeClass("focused");
                        $(iAPPSFormElement.FormElement).css("z-index", 0);
                    }, 100);
                }
                else {
                    $(iAPPSFormElement.FormElement).removeClass("focused");
                    $(iAPPSFormElement.FormElement).css("z-index", 0);
                }

                iAPPSFormElement.SetSelectedIndex($(iAPPSFormElement.FormElement).find("li").index($(iAPPSFormElement.FormElement).find("li.selected")), true);
            });

            // Click Handler
            $(this.FormElement).find("div.selectHeader").bind("click", { "iAPPSFormElement": this }, function (event) {
                var iAPPSFormElement = event.data.iAPPSFormElement;

                $(iAPPSFormElement.FormElement).css("z-index", iAPPSFormZIndex);

                if (!iAPPSFormElement.InTransition) {
                    $(iAPPSFormElement.FormElement).toggleClass("expanded").focus();
                }
                else {
                    clearTimeout(iAPPSFormElement.ControlId + "_Blur");
                    iAPPSFormElement.InTransition = false;

                    $(iAPPSFormElement.FormElement).addClass("expanded").addClass("focused");
                }
            });

            // Keydown Handler
            $(this.FormElement).bind("keydown", { "iAPPSFormElement": this }, function (event) {
                var iAPPSFormElement = event.data.iAPPSFormElement;

                if (event.keyCode == 38 || event.keyCode == 40) {
                    var iAPPSNewIndex = iAPPSFormElement.GetSelectedIndex();
                    var iAPPSOptionCount = $(iAPPSFormElement.Control).children("option").size();

                    $(iAPPSFormElement.FormElement).find("ul > li").removeClass("selected");

                    // Up Arrow
                    if (event.keyCode == 38) {
                        iAPPSNewIndex--;

                        if (iAPPSNewIndex < 0) {
                            iAPPSNewIndex = 0;
                        }
                        else if (iAPPSNewIndex >= iAPPSOptionCount) {
                            iAPPSNewIndex = iAPPSOptionCount - 1;
                        }
                    }
                    // Down Arrow
                    else if (event.keyCode == 40) {
                        iAPPSNewIndex++;

                        if (iAPPSNewIndex < 0) {
                            iAPPSNewIndex = 0;
                        }
                        else if (iAPPSNewIndex >= iAPPSOptionCount) {
                            iAPPSNewIndex = iAPPSOptionCount - 1;
                        }
                    }

                    iAPPSFormElement.SetSelectedIndex(iAPPSNewIndex, false);
                }
                // Enter
                else if (event.keyCode == 13) {
                    $(iAPPSFormElement.FormElement).removeClass("expanded");

                    iAPPSFormElement.SetSelectedIndex($(iAPPSFormElement.FormElement).find("li").index($(iAPPSFormElement.FormElement).find("li.selected")), true);
                }
                // Tab
                else if (event.keyCode == 9) {
                    return true
                }

                return false;
            });
        }
        else {
            throw "Form element '" + this.ControlId + "' has already been rendered";
        }
    }

    // Bind list of options and selected value from select element
    this.RenderListItems = function () {
        var iAPPSFormElement = "";

        $(this.Control).children("option").each(function () {
            iAPPSFormElement += "<li>";
            iAPPSFormElement += "<span>";
            iAPPSFormElement += $(this).text();
            iAPPSFormElement += "</span>";
            iAPPSFormElement += "</li>";
        });

        $(this.FormElement).find("ul").html(iAPPSFormElement);
        $(this.FormElement).find("ul").width($(this.FormElement).width());
        $(this.FormElement).find("div.selectedOption span").html($(this.Control).find("option:selected").text());
        $(this.FormElement).find("ul > li:eq(" + this.GetSelectedIndex() + ")").addClass("selected");
        $(this.FormElement).find("ul > li:first").addClass("first");
        $(this.FormElement).find("ul > li:last").addClass("last");

        $(this.FormElement).find("ul > li").bind("click", { "iAPPSFormElement": this }, function (event) {
            var iAPPSFormElement = event.data.iAPPSFormElement;

            iAPPSFormElement.SetSelectedIndex($(iAPPSFormElement.FormElement).find("ul > li").index(this), true);

            $(iAPPSFormElement.FormElement).removeClass("expanded");
        });
    }

    /******************
    * Initialization *
    ******************/

    this.RenderStyles();
    this.RenderControl();
    this.RenderListItems();
}

function iAPPSForm_TextBox(formElement) {
    /**************
    * Properties *
    **************/

    this.ControlId = $(formElement).attr("id");
    this.Control = formElement;
    this.FormElement;
    this.IsVisible = true;

    /**********
    * Methods *
    ***********/

    // Displays the rendered control on the page
    this.Show = function () {
        this.IsVisible = true;

        $(this.FormElement).show();
    }

    // Hides the rendered control on the page
    this.Hide = function () {
        this.IsVisible = false;

        $(this.FormElement).hide();
    }

    // Toggles the visibility of the rendered control on the page
    this.Toggle = function () {
        if (this.IsVisible) {
            this.Hide();
        }
        else {
            this.Show();
        }
    }

    // Returns the value of the TextBox element
    this.GetValue = function () {
        return $(this.Control).val();
    }

    // Sets the value of the TextBox element
    this.SetValue = function (newValue) {
        $(this.Control).val(newValue);
    }

    // Generates default custom styles if they have not already been rendered
    this.RenderStyles = function () {
        if ($("style#iAPPSFormTextBox").size() == 0) {
            var iAPPSFormStyles = "";

            iAPPSFormStyles += "<style id=\"iAPPSFormTextBox\" type=\"text/css\">";
            iAPPSFormStyles += "div.iAPPSFormTextBox{float: left; outline: none;}";
            iAPPSFormStyles += "div.iAPPSFormTextBox input{display: block; width: 100%; border: none; outline: none;}";
            iAPPSFormStyles += "</style>";

            $("head").append(iAPPSFormStyles);
        }
    }

    // Generates HTML and binds event handlers to custom control
    this.RenderControl = function () {
        if (typeof (this.FormElement) == "undefined") {
            var iAPPSInlineStyle = typeof ($(this.Control).attr("style")) != "undefined" ? $(this.Control).attr("style") : "";

            $(this.Control).before("<div id=\"" + iAPPSFormPrefix + this.ControlId + "\" class=\"" + $(this.Control).attr("class") + "\" style=\"" + iAPPSInlineStyle + "\"><div></div></div>");

            this.FormElement = $("div#" + iAPPSFormPrefix + this.ControlId)[0];
            $(this.FormElement).addClass("iAPPSFormTextBox").removeClass(iAPPSFormClass);

            $(this.Control).siblings("div.iAPPSFormTextBox").find("> div").append(this.Control);
            $(this.Control).width("100%");
        }
        else {
            throw "Form element '" + this.ControlId + "' has already been rendered";
        }
    }

    /******************
    * Initialization *
    ******************/

    this.RenderStyles();
    this.RenderControl();
}

function iAPPSForm_TextArea(formElement) {
    /**************
    * Properties *
    **************/

    this.ControlId = $(formElement).attr("id");
    this.Control = formElement;
    this.FormElement;
    this.IsVisible = true;

    /**********
    * Methods *
    ***********/

    // Displays the rendered control on the page
    this.Show = function () {
        this.IsVisible = true;

        $(this.FormElement).show();
    }

    // Hides the rendered control on the page
    this.Hide = function () {
        this.IsVisible = false;

        $(this.FormElement).hide();
    }

    // Toggles the visibility of the rendered control on the page
    this.Toggle = function () {
        if (this.IsVisible) {
            this.Hide();
        }
        else {
            this.Show();
        }
    }

    // Returns the value of the TextArea element
    this.GetValue = function () {
        return $(this.Control).html();
    }

    // Sets the value of the TextArea element
    this.SetValue = function (newValue) {
        $(this.Control).html(newValue);
    }

    // Generates default custom styles if they have not already been rendered
    this.RenderStyles = function () {
        if ($("style#iAPPSFormTextArea").size() == 0) {
            var iAPPSFormStyles = "";

            iAPPSFormStyles += "<style id=\"iAPPSFormTextArea\" type=\"text/css\">";
            iAPPSFormStyles += "div.iAPPSFormTextArea{float: left; outline: none;}";
            iAPPSFormStyles += "div.iAPPSFormTextArea TextArea{display: block; border: none; outline: none; overflow: auto;}";
            iAPPSFormStyles += "</style>";

            $("head").append(iAPPSFormStyles);
        }
    }

    // Generates HTML and binds event handlers to custom control
    this.RenderControl = function () {
        if (typeof (this.FormElement) == "undefined") {
            var iAPPSInlineStyle = typeof ($(this.Control).attr("style")) != "undefined" ? $(this.Control).attr("style") : "";

            $(this.Control).before("<div id=\"" + iAPPSFormPrefix + this.ControlId + "\" class=\"" + $(this.Control).attr("class") + "\" style=\"" + iAPPSInlineStyle + "\"><div></div></div>");

            this.FormElement = $("div#" + iAPPSFormPrefix + this.ControlId)[0];
            $(this.FormElement).addClass("iAPPSFormTextArea").removeClass(iAPPSFormClass);

            $(this.Control).siblings("div.iAPPSFormTextArea").find("> div").append(this.Control);
            $(this.Control).width("100%");
        }
        else {
            throw "Form element '" + this.ControlId + "' has already been rendered";
        }
    }

    /******************
    * Initialization *
    ******************/

    this.RenderStyles();
    this.RenderControl();
}
