public static string RenderFormGroupTextBox(HtmlHelper html, TextBoxModel inputModel, LabelModel labelModel)
        {
            var input = RenderControl.RenderTextBox(html, inputModel, false);
            var label = RenderControl.RenderLabel(html, labelModel ?? new LabelModel
            {
                htmlFieldName = inputModel.htmlFieldName,
                metadata = inputModel.metadata,
                htmlAttributes = new { @class = "control-label" }.ToDictionary()
            });

            bool fieldIsValid = true;

            if (inputModel != null)
                fieldIsValid = html.ViewData.ModelState.IsValidField(inputModel.htmlFieldName);

            return new FormGroup(input, label, FormGroupType.TextBoxLike, fieldIsValid).ToHtmlString();
        }
        public static HtmlString RenderTextBox(HtmlHelper html, TextBoxModel model, bool isPassword)
        {
            var combinedHtml = "{0}{1}{2}";

            model.htmlAttributes.MergeHtmlAttributes(html.GetUnobtrusiveValidationAttributes(model.htmlFieldName, model.metadata));

            if (!string.IsNullOrEmpty(model.id))
                model.htmlAttributes.Add("id", model.id);

            if (!string.IsNullOrEmpty(model.placeholder))
                model.htmlAttributes.Add("placeholder", model.placeholder);

            if(model.size != Size._NotSet)
                model.htmlAttributes.AddOrMergeCssClass("class", $"input-{model.size.ToName()}");

            model.htmlAttributes.AddOrMergeCssClass("class", "form-control");

            var input = isPassword
                ? html.Password(model.htmlFieldName, null, model.htmlAttributes.FormatHtmlAttributes()).ToHtmlString()
                : html.TextBox(model.htmlFieldName, model.value, model.format, model.htmlAttributes.FormatHtmlAttributes()).ToHtmlString();

            // account for appendString, prependString, and AppendButtons
            if (!string.IsNullOrEmpty(model.prependString) || !string.IsNullOrEmpty(model.appendString) || model.iconPrepend != Icons._not_set
                || model.iconAppend != Icons._not_set || !string.IsNullOrEmpty(model.iconPrependCustomClass) || !string.IsNullOrEmpty(model.iconAppendCustomClass))
            {
                var appendPrependContainer = new TagBuilder("div");
                appendPrependContainer.AddOrMergeCssClass("input-group");
                appendPrependContainer.AddOrMergeCssClass("mar-btm");

                var addOnPrependString = "";
                var addOnAppendString = "";
                var addOnPrependIcon = "";
                var addOnAppendIcon = "";

                var addOn = new TagBuilder("span");
                addOn.AddCssClass("input-group-addon");

                if (!string.IsNullOrEmpty(model.prependString))
                {
                    addOn.InnerHtml = model.prependString;
                    addOnPrependString = addOn.ToString();
                }

                if (!string.IsNullOrEmpty(model.appendString))
                {
                    addOn.InnerHtml = model.appendString;
                    addOnAppendString = addOn.ToString();
                }

                if (model.iconPrepend != Icons._not_set)
                {
                    addOn.InnerHtml = new Icon(model.iconPrepend, model.iconPrependIsWhite).ToHtmlString();
                    addOnPrependIcon = addOn.ToString();
                }

                if (model.iconAppend != Icons._not_set)
                {
                    addOn.InnerHtml = new Icon(model.iconAppend, model.iconAppendIsWhite).ToHtmlString();
                    addOnAppendIcon = addOn.ToString();
                }

                if (!string.IsNullOrEmpty(model.iconPrependCustomClass))
                {
                    var i = new TagBuilder("i");
                    i.AddCssClass(model.iconPrependCustomClass);
                    addOn.InnerHtml = i.ToString(TagRenderMode.Normal);
                    addOnPrependIcon = addOn.ToString();
                }

                if (!string.IsNullOrEmpty(model.iconAppendCustomClass))
                {
                    var i = new TagBuilder("i");
                    i.AddCssClass(model.iconAppendCustomClass);
                    addOn.InnerHtml = i.ToString(TagRenderMode.Normal);
                    addOnAppendIcon = addOn.ToString();
                }

                appendPrependContainer.InnerHtml = addOnPrependIcon + addOnPrependString + "{0}" + addOnAppendString + addOnAppendIcon;
                combinedHtml = appendPrependContainer.ToString(TagRenderMode.Normal) + "{1}{2}";
            }

            var helpText = model.helpText != null ? model.helpText.ToHtmlString() : string.Empty;
            var validationMessage = "";

            if (model.displayValidationMessage)
            {
                var validation = html.ValidationMessage(model.htmlFieldName).ToHtmlString();
                validationMessage = new HelpText(validation, model.validationMessageStyle).ToHtmlString();
            }

            string htmlTextBox = string.Format(combinedHtml, input, helpText, validationMessage);

            TagBuilder inputWrapper = null;

            if (!string.IsNullOrEmpty(model.inputElementWrapper))
            {
                inputWrapper = new TagBuilder(model.inputElementWrapper);

                if (model.inputElementWrapperAttributes != null)
                    inputWrapper.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(model.inputElementWrapperAttributes));

                inputWrapper.InnerHtml = htmlTextBox;
            }

            string htmlString = inputWrapper != null
                ? inputWrapper.ToString(TagRenderMode.Normal)
                : htmlTextBox;

            return new HtmlString(htmlString);
        }