using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using Kendo.Mvc.UI.Fluent;
using Kreta.BusinessLogic.Interfaces;
using Kreta.Enums.ManualEnums;
using Kreta.Framework;
using Kreta.Framework.Util;
using Kreta.Web.Classes;
using Kreta.Web.Helpers.Grid;

namespace Kreta.Web.Helpers
{
    public static class GridExtensions
    {
        /* this classes has referance on js side as well */
        public const string CheckboxClass = "gridCheckBox";
        public const string SelectCheckboxClass = "gridSelectCheckBox";
        public const string HeaderSelectCheckboxClass = "gridHeaderSelectCheckBox";
        public const string SelectRadioBtnClass = "gridSelectRadioBtn";
        public const string TextboxClass = "gridTextbox";
        public const string TextareaClass = "gridTextarea";
        public const string FormattedTextInputClass = "gridFormattedTextInput";
        public const string NumericboxClass = "gridNumericBox";
        public const string DropDownClass = "gridDropDownList";
        public const string TimePickerClass = "gridTimePicker";
        public const string GridSelectClass = "gridSelect";
        public const string GridComboBoxClass = "gridComboBox";

        public const string ToolbarTemplate = @"
            <div class=""kreta-pagerContainer"">
            <div class=""kreta-pager k-pager-wrap k-grid-pager k-widget k-floatwrap btn-group"" data-role=""pager"">
                {0}
                {1}
                {2}
                {3}
            </div>
            </div>";

        public const string ExcelExportToolbarTemplate = @"
                <button tabindex=""-1"" value="""" class=""k-button k-button-icontext"" title=""{0}"" onClick=""KretaGridHelper.exportGrid({1}, '{2}', 'undefined', 'undefined', {3})"">
                    <span class=""k-icon k-i-excel""></span>
                </button>";

        public const string PdfExportToolbarTemplate = @"
                <button class=""k-button k-button-icontext k-grid-pdf"" title=""{0}"" >
                    <span class=""k-icon k-i-pdf""></span>
                </button>";

        public const string PagerToolbarTemplate = @"
            <button type='button' class=""k-button kendoGrid-Back k-link k-pager-nav k-state-disabled"" title=""{1}"">
                <span class=""k-icon k-i-arrow-w""></span>
            </button>
            <button type='button' class=""k-button kendoGrid-Next k-link k-pager-nav k-state-disabled"" title=""{2}"">
                <span class=""k-icon k-i-arrow-e""></span>
            </button>
            {0}
            <span class=""k-label kendoGrid-PageInfo {3}"">0 - 0 / 0</span>";

        private const string FunctionCommandButtonTemplate = "<button type=\"button\" class=\"k-button k-button-icontext {0}\" href=\"javascript:void(0)\" {1} {3}><span></span>{2}</button>";

        public static GridBuilder<TFirstLevelType> KretaGrid<TFirstLevelType>(
            this HtmlHelper helper,
            IEnumerable<TFirstLevelType> dataSource,
            string name,
            string dataBoundAdditionalFunction = "")
            where TFirstLevelType : class
        {
            var grid = helper.Kendo().Grid(dataSource)
                .Name(name)
                .DataSource(source =>
                {
                    source.Ajax();
                })
                .Events(events =>
                {
                    events.DataBound($@"
                        function(e) {{
                            KretaGridHelper.init(e);
                            KretaTooltipHelper.setGridCellTooltip($("".kretaTooltipDefaultClass""), ""#kendoTooltip-defaultTemplate"");
                            KretaDateTimeHelper.SetMaskedTimepicker();
                            KretaDateTimeHelper.SetTimepicker();
                            {dataBoundAdditionalFunction}
                        }}");
                })
                .NoRecords(StringResourcesUtil.GetString(155) /*Nincs találat*/);

            return grid;
        }

        public static GridBuilder<TFirstLevelType> KretaGrid<TFirstLevelType>(
            this HtmlHelper helper,
            string name,
            GridApiUrl getUrl = null,
            GridApiUrl postUrl = null,
            GridApiUrl putUrl = null,
            GridApiUrl deleteUrl = null,

            object routeValues = null,
            bool allowScrolling = false,
            bool allowSorting = true,
            bool allowPaging = true,
            bool allowGrouping = false,
            bool allowFooter = true,
            bool allowFilterable = false,
            bool allowExcelExport = false,
            bool popupExport = false,
            string excelExportFileName = "ExcelExport",
            bool allowPdfExport = false,
            int? pageSizes = 100,
            string dataParameterFunction = "",
            string readDataFunction = "",
            string editHandlerFunction = "function(){}",
            string syncHandlerFunction = "function(){}",
            string requestEndAdditionalFunction = "",
            string dataBoundAdditionalFunction = "",
            string clientTemplate = "",
            string clientTemplateUrl = "",
            bool clientTemplateWholeDataRow = false,
            bool useToolBar = true,
            string exportColumnUrl = null,
            string exportDataUrl = null,
            bool mustShowPagerCount = true,
            bool postRead = false,
            bool batchEdit = false,
            string errorHandlerFunction = @"function(error) { 
                if (!CommonUtils.isNullOrUndefined(error) && error.status === 'customerror') { 
                    KretaWindowHelper.notification('A szolgáltatás nem elérhető.', 'error'); 
                    return;                    
                } 
                KretaWindowHelper.notification('Hiba történt az adatok betöltése közben.', 'error'); 
            }",
            //Action<DataSourceModelDescriptorFactory<TFirstLevelType>> modelDescriptor = null,

            Action<DataSourceSortDescriptorFactory<TFirstLevelType>> sort = null,
            Action<DataSourceAggregateDescriptorFactory<TFirstLevelType>> aggregates = null,
            bool showSorszam = true
        ) where TFirstLevelType : class, IKretaIdentity
        {
            var url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            var hasSzuro = false;
            var grid = helper.Kendo().Grid<TFirstLevelType>()
                .Name(name)
                .Scrollable(s =>
                {
                    s.Enabled(allowScrolling);
                    if (!allowPaging)
                    {
                        s.Virtual(true);
                    }
                })
                .Editable(editable => editable.Mode(GridEditMode.PopUp))
                .Sortable(s => s.Enabled(allowSorting))
                .Pageable(p => p.Enabled(allowPaging).PreviousNext(false).PageSizes(false).Numeric(false).Info(false))
                .Filterable(f => f.Enabled(allowFilterable))
                .Groupable(g => g.Enabled(allowGrouping).Messages(m => m.Empty(StringResourcesUtil.GetString(3482))))
                .DataSource(source =>
                {
                    var ajaxDataSource = source.Ajax().Batch(batchEdit);

                    if (!string.IsNullOrWhiteSpace(requestEndAdditionalFunction))
                    {
                        requestEndAdditionalFunction += $"(e, '{name}');";
                    }

                    var requestStartHandler = "function(e) { setTimeout(function(e) { $(\".k-loading-image\").hide(); } )}";
                    var requestEndHandler = $"function(e) {{ KretaGridHelper.initToolBar(e, '{name}'); {requestEndAdditionalFunction} }}";

                    ajaxDataSource.Events(e => e.RequestStart(requestStartHandler).RequestEnd(requestEndHandler).Error(errorHandlerFunction).Sync(syncHandlerFunction))
                        .Model(model => { model.Id(p => p.ID); });

                    if (!string.IsNullOrWhiteSpace(readDataFunction))
                    {
                        dataParameterFunction = readDataFunction;
                    }
                    else
                    {
                        if (!string.IsNullOrWhiteSpace(dataParameterFunction))
                        {
                            dataParameterFunction = $"function(){{ return KretaGridHelper.getSearchParameters('#{dataParameterFunction}'); }}";
                            hasSzuro = true;
                        }
                        else
                        {
                            dataParameterFunction = "function(){ return { data: JSON.stringify({}) }; }";
                        }
                    }

                    if (getUrl != null)
                    {
                        var type = postRead ? HttpVerbs.Post : HttpVerbs.Get;
                        if (!pageSizes.HasValue)
                        {
                            pageSizes = 0;
                        }
                        ajaxDataSource.PageSize(pageSizes.Value).Read(read =>
                            read.Data(dataParameterFunction)
                                .Url(url.HttpRouteUrl(getUrl.Route, getUrl.RouteValues)
                                ).Type(type));
                    }
                    if (postUrl != null)
                    {
                        ajaxDataSource.Create(create => create.Data(dataParameterFunction).Url(url.HttpRouteUrl(postUrl.Route, postUrl.RouteValues)).Type(HttpVerbs.Post));
                    }
                    if (putUrl != null)
                    {
                        ajaxDataSource.Update(update => update.Data(dataParameterFunction).Url(url.HttpRouteUrl(putUrl.Route, putUrl.RouteValues)).Type(HttpVerbs.Put));
                    }
                    if (deleteUrl != null)
                    {
                        ajaxDataSource.Destroy(destroy => destroy.Data(dataParameterFunction).Url(url.HttpRouteUrl(deleteUrl.Route, deleteUrl.RouteValues)).Type(HttpVerbs.Delete));
                    }

                    if (sort != null)
                    {
                        ajaxDataSource.Sort(sort);
                    }
                    if (aggregates != null)
                    {
                        ajaxDataSource.Aggregates(aggregates);
                    }
                })
                .AutoBind(!hasSzuro)
                .Events(events =>
                {
                    events.DataBound($@"
                        function(e) {{
                            KretaGridHelper.init(e);
                            KretaTooltipHelper.setGridCellTooltip($("".kretaTooltipDefaultClass""), ""#kendoTooltip-defaultTemplate"");
                            KretaDateTimeHelper.SetMaskedTimepicker();
                            KretaDateTimeHelper.SetTimepicker();
                            {dataBoundAdditionalFunction}
                        }}").Edit(editHandlerFunction);
                })
                .NoRecords(StringResourcesUtil.GetString(155) /*Nincs találat*/);

            if (showSorszam)
            {
                var regex = new Regex("^[^a-zA-Z_$]|[^\\w$]");
                var rowNumberName = regex.Replace(name, "_") + "RowNumber";
                grid.Events(events =>
                {
                    events.DataBinding($@"function() {{
                        var currrentRowNumber = 1;
                        if (!CommonUtils.isUndefined(this.dataSource.page()) && !CommonUtils.isUndefined(this.dataSource.pageSize())) {{
                            currrentRowNumber = currrentRowNumber + (this.dataSource.page() - 1) * this.dataSource.pageSize();
                        }}
                        {rowNumberName} = currrentRowNumber;
                    }}");
                });
                grid.Columns(c => c.Template(t => t.ToString())
                    .Title("#")
                    .Width("42px")
                    .HeaderHtmlAttributes(new { @class = "kretaRowNumberHeader" })
                    .HtmlAttributes(new { title = $"#: {rowNumberName} #", @class = "kretaEllipsis kretaRowNumber" })
                    //NOTE: Azért van szüksége "%2B"-re mert a ClientTemplate nem tudja kirenderelni a "+" jelet!
                    .ClientTemplate($"#= {rowNumberName}%2B%2B #"));
            }

            if (exportColumnUrl == null || exportDataUrl == null)
            {
                grid.Excel(excel => excel
                    .FileName(name + " Grid Export.xlsx")
                    .Filterable(true)
                    .ProxyURL(url.Action("Excel_Export_Save", "Layout", new { area = string.Empty }))
                    .ForceProxy(true)
                    .AllPages(true));
            }
            else
            {
                grid.HtmlAttributes(new { data_exportColumnUrl = exportColumnUrl, data_exportDataUrl = exportDataUrl });
            }

            bool isMultipleGrid = false;
            if (!string.IsNullOrWhiteSpace(clientTemplate) && !string.IsNullOrWhiteSpace(clientTemplateUrl))
            {
                grid.ClientDetailTemplateId(clientTemplate);
                grid.HtmlAttributes(new { clientTemplateUrl, clientTemplateWholeDataRow });
                isMultipleGrid = true;
            }

            if (useToolBar)
            {
                if (allowExcelExport)
                {
                    grid.Excel(excel => excel
                        .FileName(name + " Grid Export.xlsx")
                        .Filterable(true)
                        .ProxyURL(url.Action("Excel_Export_Save", "Layout", new { area = string.Empty }))
                        .ForceProxy(true)
                        .AllPages(true));
                }

                if (allowPdfExport)
                {
                    grid.Pdf(pdf => pdf
                        .AllPages()
                        .FileName(name + " Grid Export.pdf")
                        .ProxyURL(url.Action("Pdf_Export_Save", "Layout", new { area = string.Empty }))
                        .ForceProxy(true));
                }

                grid.ToolBar(
                    tools =>
                    {
                        tools.Template(GetToolbarHtml(name, helper, allowPaging, pageSizes.Value, isMultipleGrid, allowExcelExport,
                            allowPdfExport, exportColumnUrl, exportDataUrl, mustShowPagerCount, excelExportFileName, popupExport));
                    });
            }
            return grid;
        }

        /// <summary>
        /// Kendo grid patch az unicode karakterek támogatásához. Enélkül elszáll a detail template. (Most csak a hosszú í-re)
        /// </summary>
        /// <typeparam name="TDataType"></typeparam>
        /// <param name="gridBuilder"></param>
        /// <returns></returns>
        public static MvcHtmlString ToGridClientTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder) where TDataType : class
        {
            var initial = gridBuilder.ToClientTemplate().ToHtmlString();
            var corrected = initial.Replace("&#237;", "í");
            return new MvcHtmlString(corrected);
        }

        public static GridBuilder<TDataType> LinkButtonColumn<TDataType, TValue>(this GridBuilder<TDataType> gridBuilder,
            string linkTitle, Expression<Func<TDataType, TValue>> parameterName, string functionClientName, GridButtonsEnum buttonType, bool showHeader = true,
            string hiddenCondition = "false", bool enabled = true, string format = null, string customField = null, string width = null) where TDataType : class
        {
            if (!enabled)
            {
                return gridBuilder;
            }

            var fieldName = ExpressionHelper.GetExpressionText(parameterName);
            if (!string.IsNullOrWhiteSpace(format))
            {
                fieldName = $"kendo.format(\"{format}\", {fieldName})";
            }

            string template = $"<a class=\"gridLinkButton {buttonType.GetStringValue()} \" onclick='KretaGridHelper.rowFunctionCall($(this),\"{gridBuilder.ToComponent().Name}\",{functionClientName});' title=\"{linkTitle}\" # hiddencondition # >#:{(!string.IsNullOrWhiteSpace(customField) ? customField : fieldName)}#</a>";

            template = template.Replace("hiddencondition", "if ( " + hiddenCondition + ") {  # style = 'display:none' #  }");

            if (!string.IsNullOrWhiteSpace(width))
            {
                if (!showHeader)
                {
                    return gridBuilder.Columns(n => n.Template(o => o.ToString()).ClientTemplate(template).Width(width).HeaderHtmlAttributes(new { style = "display:none" }).HeaderTemplate("<text></text>").Title(""));
                }

                return gridBuilder.Columns(c => c.Bound(parameterName).Template(t => t.ToString()).ClientTemplate(template).Width(width));
            }

            if (!showHeader)
            {
                return gridBuilder.Columns(n => n.Template(o => o.ToString()).ClientTemplate(template).Width(40).HeaderHtmlAttributes(new { style = "display:none" }).HeaderTemplate("<text></text>").Title(""));
            }

            return gridBuilder.Columns(c => c.Bound(parameterName).Template(t => t.ToString()).ClientTemplate(template));
        }

        public static GridBuilder<TDataType> RowFunction<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, List<RowFunction> rowFunctions) where TDataType : class
        {
            SetGridBuilderColumns(gridBuilder, rowFunctions, html, false);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> RowFunction<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, List<RowFunction> rowFunctions, string header) where TDataType : class
        {
            SetGridBuilderColumns(gridBuilder, rowFunctions, html, false, header: header);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> RowFunction<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, List<RowFunction> rowFunctions, int iconCount) where TDataType : class
        {
            SetGridBuilderColumns(gridBuilder, rowFunctions, html, false, iconCount: iconCount);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> ConditionalRowFunction<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, List<RowFunction> rowFunctions, string isVisibleRowFunctionJsFunctionName, int? iconCount = null) where TDataType : class
        {
            SetGridBuilderColumns(gridBuilder, rowFunctions, html, true, isVisibleRowFunctionJsFunctionName, iconCount: iconCount);
            return gridBuilder;
        }

        private static void SetGridBuilderColumns<TDataType>(GridBuilder<TDataType> gridBuilder, List<RowFunction> rowFunctions, HtmlHelper html, bool isConditional, string isVisibleRowFunctionJsFunctionName = null, string header = null, int? iconCount = null) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;

            var htmlAttributes = new Dictionary<string, object>
            {
                {"class", "rowFunction"},
                {"data-rowFunctionParent", gridName}
            };

            string clientTemplate;
            if (rowFunctions.All(x => x.IconEnum != null))
            {
                var minWidth = iconCount.HasValue ? iconCount.Value * 40 : 80;
                htmlAttributes.Add("style", $"min-width: {minWidth}px;{(iconCount.HasValue ? $"width: {iconCount.Value * 40}px" : "")}");
                clientTemplate = GetRowFunctionClientTemplateIcon(gridName, html, rowFunctions);
            }
            else
            {
                clientTemplate = GetRowFunctionClientTemplate(gridName, html, rowFunctions);
            }
            if (!string.IsNullOrWhiteSpace(clientTemplate))
            {
                var sb = new StringBuilder();
                if (isConditional)
                {
                    sb.AppendFormat("#if({0}(data)){{#", isVisibleRowFunctionJsFunctionName);
                    sb.Append(clientTemplate);
                    sb.Append("#}#");
                }
                else
                {
                    sb.Append(clientTemplate);
                }
                gridBuilder.Columns(c => c.Template(t => t.ToString())
                    .HtmlAttributes(htmlAttributes)
                    .HeaderHtmlAttributes(htmlAttributes)
                    .ClientTemplate(sb.ToString())
                    .HeaderTemplate(header)
                    );
            }
        }

        private static string GetRowFunctionClientTemplate(string gridName, HtmlHelper html, List<RowFunction> rowFunctions)
        {
            var clientTemplate = html.Kendo()
                .Menu()
                .Name(gridName + "_menu_#=ID#" + "_" + Guid.NewGuid())
                .Direction(MenuDirection.Left)
                .OpenOnClick(true)
                .Items(its =>
                {
                    its.Add().Items(nested =>
                    {
                        foreach (var function in rowFunctions)
                        {
                            var menuItem =
                                nested.Add()
                                    .Text(function.NameResourceId.HasValue
                                        ? StringResourcesUtil.GetString(function.NameResourceId.Value)
                                        : function.Name);
                            if (!string.IsNullOrWhiteSpace(function.ClientAction))
                            {
                                menuItem.HtmlAttributes(new
                                {
                                    //@onclick = string.Format("KretaGridHelper.rowFunctionCall($(this),'{0}',{1});", gridName, function.ClientAction)
                                    @onclick = $"KretaGridHelper.rowFunctionCall($(this),'{gridName}',{function.ClientAction});"
                                });
                            }
                        }
                    });
                }).ToClientTemplate()
                .ToHtmlString();
            return clientTemplate;
        }

        private static string GetRowFunctionClientTemplateIcon(string gridName, HtmlHelper html, List<RowFunction> rowFunctions)
        {
            var sb = new StringBuilder();

            foreach (var item in rowFunctions)
            {
                if (item.IsConditional)
                {
                    sb.AppendFormat("#if({0}(data)){{#", item.IsVisibleRowFunctionJsFunctionName);
                }
                var buttonTemplate = "<a title=\"{1}\" href=\"javascript:void(0)\" {0}><i style=\"font-size: 22px;\" class=\"{2}\" aria-hidden=\"true\"></i></a>&nbsp;&nbsp;";

                var clientEvent = string.Empty;
                if (!string.IsNullOrWhiteSpace(item.ClientAction))
                {
                    clientEvent = string.Format(@"onclick = ""KretaGridHelper.rowFunctionCall($(this),'{0}',{1}{2});""", gridName, item.ClientAction, (item.SendSender) ? ",true" : "");
                }

                var iconClass = "";
                if (item.IconEnum == GridRowFunctionIconEnum.Adatok)
                    iconClass = "fa fa-search";
                if (item.IconEnum == GridRowFunctionIconEnum.Modositas)
                    iconClass = "fa fa-pencil";
                if (item.IconEnum == GridRowFunctionIconEnum.Torles)
                    iconClass = "fa fa-trash";
                if (item.IconEnum == GridRowFunctionIconEnum.Aktival)
                    iconClass = "fa fa-check-circle";
                if (item.IconEnum == GridRowFunctionIconEnum.Uj)
                    iconClass = "fa fa-plus";
                if (item.IconEnum == GridRowFunctionIconEnum.Statisztika)
                    iconClass = "fa fa-bar-chart";
                if (item.IconEnum == GridRowFunctionIconEnum.HaromPont)
                    iconClass = "fa fa-ellipsis-h";
                if (item.IconEnum == GridRowFunctionIconEnum.KorbenX)
                    iconClass = "fa fa-times-circle";
                if (item.IconEnum == GridRowFunctionIconEnum.Letoltes)
                    iconClass = "fa fa-download";
                if (item.IconEnum == GridRowFunctionIconEnum.Ujra)
                    iconClass = "fa fa-refresh";
                if (item.IconEnum == GridRowFunctionIconEnum.Vagolap)
                    iconClass = "fa fa-clipboard";
                if (item.IconEnum == GridRowFunctionIconEnum.Kep)
                    iconClass = "fa fa-image";
                if (item.IconEnum == GridRowFunctionIconEnum.Excel)
                    iconClass = "fa fa-file-excel-o";
                if (item.IconEnum == GridRowFunctionIconEnum.Word)
                    iconClass = "fa fa-file-word-o";
                if (item.IconEnum == GridRowFunctionIconEnum.Pdf)
                    iconClass = "fa fa-file-pdf-o";
                if (item.IconEnum == GridRowFunctionIconEnum.Feltoltes)
                    iconClass = "fa fa-upload";
                if (item.IconEnum == GridRowFunctionIconEnum.Ban)
                    iconClass = "fa fa-ban";
                if (item.IconEnum == GridRowFunctionIconEnum.TimesCircle)
                    iconClass = "fa fa-times-circle-o";
                var title = item.NameResourceId.HasValue ? StringResourcesUtil.GetString(item.NameResourceId.Value) : item.Name;

                sb.AppendFormat(buttonTemplate, clientEvent, title, iconClass);
                if (item.IsConditional)
                {
                    if (!item.IsMultipleConditionalColumn)
                    {
                        sb.Append("#}#");
                    }
                    else
                    {
                        // Ha nem jelenik meg az elem, akkor a helyét kitöltjük, hogy ne "essenek" össze a gombok.
                        sb.AppendFormat("#}}else{{#<i style=\"font-size: 22px; visibility: hidden;\" class=\"{0}\" aria-hidden=\"true\"></i></a>&nbsp;&nbsp;#}}#", iconClass);
                    }
                }
            }

            return sb.ToString();
        }

        public static GridBuilder<TDataType> FunctionCommand<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, List<FunctionCommand> functions, int breakIndex = 6) where TDataType : class
        {
            gridBuilder.ToolBar(tools =>
            {
                var component = gridBuilder.ToComponent();
                var gridName = component.Name;
                var sb = new StringBuilder();

                sb.Append("<div class='kendo-gridFunctionKommand'>");

                for (int index = 0; index < functions.Count; index++)
                {
                    FunctionCommand function = functions[index];

                    if (function.NestedCommands != null && function.NestedCommands.Any())
                    {
                        var text = function.NameResourceId.HasValue ? StringResourcesUtil.GetString(function.NameResourceId.Value) : function.Name;

                        sb.Append(GetFunctionCommandMenu(html, gridName, $"FunctionCommandMenu_{index}", text, function.NestedCommands));
                    }
                    else
                    {
                        sb.Append(GetFunctionCommandButton(gridName, function));
                    }
                }

                sb.Append("</div>");

                if (!string.IsNullOrWhiteSpace(component.ToolBar.Template.Html))
                {
                    sb.Append(component.ToolBar.Template.Html);
                }

                tools.Template(sb.ToString());
            });

            return gridBuilder;
        }

        public static GridBuilder<TDataType> HeaderCustomContent<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string content) where TDataType : class
        {
            gridBuilder.ToolBar(tools =>
            {
                var component = gridBuilder.ToComponent();
                var sb = new StringBuilder();

                sb.Append("<div class='kendo-gridHeaderCustomContent'>");
                sb.Append(content);
                sb.Append("</div>");

                if (!string.IsNullOrWhiteSpace(component.ToolBar.Template.Html))
                {
                    sb.Append(component.ToolBar.Template.Html);
                }

                tools.Template(sb.ToString());
            });

            return gridBuilder;
        }

        private static string GetFunctionCommandButton(string gridName, FunctionCommand functionCommand)
        {
            var clientEvent = string.Empty;
            var text = functionCommand.NameResourceId.HasValue ? StringResourcesUtil.GetString(functionCommand.NameResourceId.Value) : functionCommand.Name;

            if (!string.IsNullOrWhiteSpace(functionCommand.ClientAction))
            {
                clientEvent = string.Format(@"onclick = ""KretaGridHelper.functionCommandCall($(this),'{0}',{1});""", gridName, functionCommand.ClientAction);
            }

            return string.Format(FunctionCommandButtonTemplate,
                functionCommand.Classes,
                functionCommand.Enabled ? clientEvent : string.Empty,
                text,
                !functionCommand.Enabled ? @"disabled = 'true'" : string.Empty);
        }

        private static string GetFunctionCommandMenu(HtmlHelper html, string gridName, string name, string text, List<FunctionCommand> functions)
        {
            var menu = html.Kendo().Menu().Name($"{gridName}_{name}")
                .Items(its =>
                {
                    its.Add().Text(text).Items(nested =>
                    {
                        foreach (var function in functions)
                        {
                            var menuItem = nested.Add().Text(function.NameResourceId.HasValue ? StringResourcesUtil.GetString(function.NameResourceId.Value) : function.Name);
                            if (!string.IsNullOrWhiteSpace(function.ClientAction))
                            {
                                menuItem.HtmlAttributes(new { onclick = string.Format("KretaGridHelper.functionCommandCall($(this),'{0}',{1});", gridName, function.ClientAction) });
                            }
                            if (!function.Enabled)
                            {
                                menuItem.HtmlAttributes(new { disabled = "true" });
                            }
                        }
                    });
                });

            return menu.ToHtmlString();
        }

        //[Obsolete("Use ConditionColumn insted")]
        public static GridBuilder<TDataType> EditableComboBoxColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, string url, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null, bool maxWidth = false, bool disabled = false, string openEvent = "", Expression<Func<TDataType, object>> conditionExpression = null) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var proprtyName = GetProperyNameFromExpression(expression);
            var uniqueName = $"{gridName}_{proprtyName}_#=ID#";

            var conditionproprtyName = string.Empty;
            if (conditionExpression != null)
                conditionproprtyName = GetProperyNameFromExpression(conditionExpression);

            var sb = new StringBuilder();

            var htmlAttr = new Dictionary<string, object>
            {
                {"data-DropdownGroup", $"{gridName}_{proprtyName}"},
                {"data-rowInputName", proprtyName}
            };
            if (maxWidth)
            {
                htmlAttr.Add("class", "gridInputMaxWidth");
            }
            if (disabled)
            {
                htmlAttr.Add("disabled", "disabled");
            }

            var widget = html.KretaComboBox(uniqueName, null, dataTextField, datavalueField, "", groupName, groupType, true, true);
            if (!string.IsNullOrWhiteSpace(openEvent))
                widget.Events(e => e.DataBound(openEvent));

            if (conditionExpression != null)
            {
                sb.AppendFormat("#if({0}){{#", conditionproprtyName);
                sb.AppendFormat("<span> #:{0}# </span>", proprtyName);
                sb.Append("#}else{#");
            }

            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(widget.HtmlAttributes(htmlAttr).ToClientTemplate().ToHtmlString());
            sb.Append("#}else{#");

            htmlAttr.Add("value", $"#:{proprtyName}#");
            sb.Append(widget.HtmlAttributes(htmlAttr).ToClientTemplate().ToHtmlString());

            sb.Append("#}#");
            if (conditionExpression != null)
                sb.Append("#}#");

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .HtmlAttributes(new { @class = DropDownClass, data_inputParentGrid = gridName, data_dropdownUrl = url, data_uddlId = uniqueName }).ClientTemplate(
                    sb.ToString()
                ));

            return gridBuilder;
        }

        [Obsolete("Use ConditionColumn insted")]
        public static GridBuilder<TDataType> EditableDropDownColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int intTitle, string url, Expression<Func<TDataType, object>> conditionExpression, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null, bool maxWidth = false, string customClass = null) where TDataType : class
        {
            return EditableDropDownColumn(gridBuilder, html, StringResourcesUtil.GetString(intTitle), url, conditionExpression, expression, dataTextField, datavalueField, groupName, groupType, maxWidth, customClass);
        }

        [Obsolete("Use ConditionColumn insted")]
        public static GridBuilder<TDataType> EditableDropDownColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, string url, Expression<Func<TDataType, object>> conditionExpression, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null, bool maxWidth = false, string customClass = null) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var proprtyName = GetProperyNameFromExpression(expression);
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);
            var conditionproprtyName = GetProperyNameFromExpression(conditionExpression);
            var sb = new StringBuilder();

            var htmlAttr = new Dictionary<string, object>();
            htmlAttr.Add("data-DropdownGroup", string.Format("{0}_{1}", gridName, proprtyName));
            htmlAttr.Add("data-rowInputName", proprtyName);
            if (maxWidth)
            {
                htmlAttr.Add("class", "gridInputMaxWidth");
            }

            sb.AppendFormat("#if({0}){{#", conditionproprtyName);
            sb.AppendFormat("<span> #:{0}# </span>", proprtyName);
            sb.Append("#}else{#");
            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(html.KretaDropdownList(uniqueName, null, dataTextField, datavalueField, groupName, groupType).HtmlAttributes(htmlAttr)
                .ToClientTemplate().ToHtmlString());
            sb.Append("#}else{#");

            htmlAttr.Add("value", string.Format("#:{0}#", proprtyName));
            sb.Append(html.KretaDropdownList(uniqueName, null, dataTextField, datavalueField, groupName, groupType).HtmlAttributes(htmlAttr).ToClientTemplate().ToHtmlString());
            sb.Append("#}#");
            sb.Append("#}#");

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .HtmlAttributes(new { @class = DropDownClass + (!string.IsNullOrWhiteSpace(customClass) ? " " + customClass : string.Empty), @data_inputParentGrid = gridName, @data_dropdownUrl = url, @data_dropdownGroupCustomOrder = "desc", @data_uddlId = uniqueName }).ClientTemplate(
                    sb.ToString()
                ));

            return gridBuilder;
        }

        public static string TextAreaForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, Expression<Func<TDataType, object>> expression, int rows = 1, Dictionary<string, object> htmlAttr = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{proprtyName}_#=ID#";

            if (htmlAttr == null)
            {
                htmlAttr = new Dictionary<string, object>();
            }
            htmlAttr = htmlAttr.Union(new Dictionary<string, object>
            {
                {"data-textareaGroup", $"{gridName}_{proprtyName}"},
                {"data-rowInputName", proprtyName}
            }).ToDictionary(k => k.Key, v => v.Value);
            var sb = new StringBuilder();
            sb.AppendFormat("<div class='{0}' data-inputParentGrid='{1}'>", TextareaClass, gridName);
            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(html.KretaTextArea(uniqueName, new List<string>(), rows, htmlAttr).ToHtmlString());
            sb.Append("#} else {#");
            sb.Append(html.KretaTextArea(uniqueName, new List<string> { $"#:{proprtyName}#" }, rows, htmlAttr).ToHtmlString());
            sb.Append("#}#");
            sb.Append("</div>");

            return sb.ToString();
        }

        public static string TextBoxForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, Expression<Func<TDataType, object>> expression, Dictionary<string, object> htmlAttr = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{proprtyName}_#=ID#";

            if (htmlAttr == null)
            {
                htmlAttr = new Dictionary<string, object>();
            }
            htmlAttr = htmlAttr.Union(new Dictionary<string, object>
            {
                {"data-textboxGroup", $"{gridName}_{proprtyName}"},
                {"data-rowInputName", proprtyName}
            }).ToDictionary(k => k.Key, v => v.Value);

            var undefinedPropertyHtmlAttr = htmlAttr.Union(new Dictionary<string, object>
            {
                {"value", ""},
            }).ToDictionary(k => k.Key, v => v.Value);

            var definedPropertyHtmlAttr = htmlAttr.Union(new Dictionary<string, object>
            {
                {"value", $"#:{proprtyName}#"}
            }).ToDictionary(k => k.Key, v => v.Value);

            var sb = new StringBuilder();
            sb.AppendFormat("<div class='{0}' data-inputParentGrid='{1}'>", TextboxClass, gridName);
            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(html.KretaTextBox(uniqueName, true, undefinedPropertyHtmlAttr).ToClientTemplate().ToHtmlString());
            sb.Append("#} else {#");
            sb.Append(html.KretaTextBox(uniqueName, true, definedPropertyHtmlAttr).ToClientTemplate().ToHtmlString());
            sb.Append("#}#");
            sb.Append("</div>");

            return sb.ToString();
        }

        public static string KretaFormattedTextInputForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, Expression<Func<TDataType, object>> expression, Dictionary<string, object> htmlAttributes = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{proprtyName}_#=ID#";

            if (htmlAttributes == null)
            {
                htmlAttributes = new Dictionary<string, object>();
            }

            var defaultHtmlAttributes = new Dictionary<string, object>
            {
                {"id", uniqueName},
                {"name", uniqueName},
                {"class", "k-kretaFormattedTextInput"},
                {"contenteditable", true}
            };
            if (htmlAttributes.ContainsKey("class"))
            {
                defaultHtmlAttributes["class"] += $" {htmlAttributes["class"]}";
                htmlAttributes.Remove("class");
            }
            htmlAttributes = defaultHtmlAttributes.Union(htmlAttributes).ToDictionary(k => k.Key, v => v.Value);

            var stringBuilder = new StringBuilder();
            stringBuilder.AppendFormat("<div class='{0}' data-inputParentGrid='{1}'>", FormattedTextInputClass, gridName);
            stringBuilder.Append("<div ");
            foreach (var item in htmlAttributes)
            {
                stringBuilder.Append(item.Key + "='" + item.Value + "'");
            }
            stringBuilder.Append(">");
            stringBuilder.AppendFormat("#if(!CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            stringBuilder.Append($"#:{proprtyName}#");
            stringBuilder.Append("#}#");
            stringBuilder.Append("</div>");
            stringBuilder.Append("</div>");

            return stringBuilder.ToString();
        }

        public static GridBuilder<TDataType> KretaFormattedTextInputForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, Expression<Func<TDataType, object>> expression, int? width = null) where TDataType : class
        {
            if (width == null)
            {
                width = 0;
            }
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width.Value)
                .Title(title)
                .ClientTemplate(
                    gridBuilder.KretaFormattedTextInputForColumnTemplate(html, expression)
                ));

            return gridBuilder;
        }

        public static string NumericBoxForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, Expression<Func<TDataType, object>> expression, int? min = null, int? max = null, int? precision = null, double step = 1, Dictionary<string, object> htmlAttr = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{proprtyName}_#=ID#";
            if (htmlAttr == null)
            {
                htmlAttr = new Dictionary<string, object>();
            }
            htmlAttr = htmlAttr.Union(new Dictionary<string, object>
            {
                {"data-numericboxGroup", $"{gridName}_{proprtyName}"},
                {"value", $"#:{proprtyName}#"},
                {"data-rowInputName", proprtyName}
            }).ToDictionary(k => k.Key, v => v.Value);

            var control = html.KretaNumeric(uniqueName, htmlAttr).Step(step);
            if (min.HasValue)
            {
                control.Min(min.Value);
            }
            if (max.HasValue)
            {
                control.Max(max.Value);
            }
            if (precision.HasValue)
            {
                // HOWTO: -decimals is applicable when the widget is focused -format is applicable when the widget is not focused
                control.Decimals(precision.Value);
                control.Format("n" + precision.Value);
            }

            return $"<div class='{NumericboxClass}' data-inputParentGrid='{gridName}'>{control.ToClientTemplate().ToHtmlString()}</div>";
        }

        public static string SelectForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper<TDataType> html, Expression<Func<TDataType, object>> expression, List<SelectListItem> list, bool hasTooltip = false, string customClickFunctionName = null) where TDataType : class
        {
            return gridBuilder.SelectForColumnTemplate(html, expression, list.Select(x => new ExtendedSelectListItem(x)).ToList(), hasTooltip, customClickFunctionName);
        }

        public static string SelectForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper<TDataType> html, Expression<Func<TDataType, object>> expression, List<ExtendedSelectListItem> list, bool hasTooltip = false, string customClickFunctionName = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);
            var value = string.Format("#:{0}#", proprtyName);
            return string.Format("<div class='{0}' data-inputParentGrid='{1}'>{2}</div>",
                GridSelectClass,
                gridName,
                html.KretaSelectorForGrid(uniqueName, proprtyName, value, expression, list, hasTooltip, customClickFunctionName).ToHtmlString());
        }

        public static string ComboBoxForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper<TDataType> html, Expression<Func<TDataType, object>> expression, string url) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);
            var value = string.Format("#:{0}#", proprtyName);
            return string.Format("<div class='{0}' data-inputParentGrid='{1}'>{2}</div>",
                GridSelectClass,
                gridName,
                html.KretaDropdownList(uniqueName, url).ToClientTemplate().ToHtmlString());
        }

        public static string ComboBoxForColumnTemplateWidthValue<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper<TDataType> html, Expression<Func<TDataType, object>> expression, string url, string changeEvent = "") where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);
            var value = string.Format("#:{0}#", proprtyName);

            if (string.IsNullOrWhiteSpace(changeEvent))
            {
                return string.Format("<div class='{0}' data-inputParentGrid='{1}'>{2}</div>",
                    GridSelectClass,
                    gridName,
                    html.KretaDropdownList(uniqueName, url).Value(value).ToClientTemplate().ToHtmlString());
            }

            return string.Format("<div class='{0}' data-inputParentGrid='{1}'>{2}</div>",
                    GridSelectClass,
                    gridName,
                    html.KretaDropdownList(uniqueName, url).Value(value).Events(e => e.DataBound(changeEvent).Change(changeEvent)).ToClientTemplate().ToHtmlString());
        }

        public static string ComboBoxForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string url, Expression<Func<TDataType, object>> expression, List<string> classList = null, string changeEvent = "") where TDataType : class
        {
            return GetComboBoxForColumnTemplate(gridBuilder, html, url, expression, classList, false, changeEvent);
        }

        public static string GroupedComboBoxForColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string url, Expression<Func<TDataType, object>> expression, List<string> classList = null, string changeEvent = "") where TDataType : class
        {
            return GetComboBoxForColumnTemplate(gridBuilder, html, url, expression, classList, true, changeEvent);
        }

        private static string GetComboBoxForColumnTemplate<TDataType>(GridBuilder<TDataType> gridBuilder, HtmlHelper html, string url, Expression<Func<TDataType, object>> expression, List<string> classList, bool isGrouped, string changeEvent) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var propertyName = GetProperyNameFromExpression(expression);
            var id = $"{gridName}_{propertyName}_#=ID#";

            var classString = string.Empty;
            if (classList != null)
            {
                classString = string.Join(" ", classList);
            }
            var valueString = string.Format(@"# if ({0} != null) {{##: {0} ##}} #", propertyName);
            var htmlAttributes = new Dictionary<string, object>
            {
                {"class", classString},
                {"value", valueString},
                {"data-rowInputName", propertyName}
            };

            var combobox = html.KretaGroupableComboBox(id, url, isGrouped, htmlAttributes);
            if (!string.IsNullOrWhiteSpace(changeEvent))
            {
                combobox.Events(e => e.DataBound(changeEvent).Change(changeEvent));
            }
            var comboBoxHtmlString = combobox.ToClientTemplate().ToHtmlString();

            var result = $"<div class='{GridComboBoxClass}' data-inputParentGrid='{gridName}'>{comboBoxHtmlString}</div>";
            return result;
        }

        /// <summary>
        /// Extension method for the model boolean columns.
        /// </summary>
        public static GridBuilder<TDataType> CheckBoxColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, string name, Expression<Func<TDataType, bool>> parameter, bool editable = false, string uniqueNameId = null, bool addHeaderTitle = false) where TDataType : class
        {
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .ClientTemplate(
                    CheckBoxColumnTemplate(gridBuilder, name, parameter, editable, uniqueNameId)
                )
                .HeaderTemplate(addHeaderTitle ? "<span class='k-link'>" + name + "</span>" : ""));

            return gridBuilder;
        }

        public static string CheckBoxColumnTemplate<TDataType>(this GridBuilder<TDataType> gridBuilder, string name, Expression<Func<TDataType, bool>> parameter, bool editable = false, string uniqueNameId = null) where TDataType : class
        {
            var fieldName = ExpressionHelper.GetExpressionText(parameter);

            var checkboxTemplate = "<input type='checkbox' id='{0}' data-rowInputName='{1}' class='k-checkbox' {2}value='#: " + fieldName + "#'# if (" + fieldName + ") {{ #checked='checked'# }} #/><label class='k-checkbox-label' for='{0}'></label>";
            var gridName = gridBuilder.ToComponent().Name;

            string uniqueNameTemplate = "{0}_{1}_";
            if (string.IsNullOrWhiteSpace(uniqueNameId))
                uniqueNameTemplate += "#=ID#";
            else
                uniqueNameTemplate += "#=" + uniqueNameId + "#";
            var uniqueName = string.Format(uniqueNameTemplate, gridBuilder.ToComponent().Name, name);

            var g = string.Format("<div class='{0}' data-inputParentGrid='{1}'>{2}</div>",
                CheckboxClass,
                gridName,
                string.Format(checkboxTemplate, uniqueName, name, editable ? string.Empty : "disabled='disabled' "));
            return g;
        }

        /// <summary>
        /// Select check box for data rows
        /// </summary>
        public static GridBuilder<TDataType> SelectBoxColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, bool isTrue = false) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, "chk");
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(28)
                .Title(html.KretaCheckBox(gridName + "_chk", StringResourcesUtil.GetString(title), isTrue, true, new Dictionary<string, object>() { { "class", SelectCheckboxClass }, { "onClick", "KretaGridHelper.selectAll($(this),'" + gridName + "')" } }).ToClientTemplate().ToHtmlString())
                .HeaderHtmlAttributes(new { @class = HeaderSelectCheckboxClass })
                .HtmlAttributes(new { @class = SelectCheckboxClass, @data_inputParentGrid = gridName }).ClientTemplate(
                    html.KretaCheckBox(uniqueName, string.Empty, isTrue, true, new Dictionary<string, object>() { { "data-selectGroup", gridName }, { "data-rowInputName", "chk" } }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> SelectBoxColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, bool isTrue = false, int width = 28) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, "chk");
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width)
                .Title(html.KretaCheckBox(gridName + "_chk", title, isTrue, true, new Dictionary<string, object>() { { "class", SelectCheckboxClass }, { "onClick", "KretaGridHelper.selectAll($(this),'" + gridName + "')" } }).ToClientTemplate().ToHtmlString())
                .HeaderHtmlAttributes(new { @class = HeaderSelectCheckboxClass })
                .HtmlAttributes(new { @class = SelectCheckboxClass, @data_inputParentGrid = gridName }).ClientTemplate(
                    html.KretaCheckBox(uniqueName, string.Empty, isTrue, true, new Dictionary<string, object>() { { "data-selectGroup", gridName }, { "data-rowInputName", "chk" } }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> SelectBoxColumnByUID<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, bool isTrue = false, int width = 28) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=uid#", gridName, "chk");
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width)
                .Title(html.KretaCheckBox(gridName + "_chk", title, isTrue, true, new Dictionary<string, object>() { { "class", SelectCheckboxClass }, { "onClick", "KretaGridHelper.selectAll($(this),'" + gridName + "')" } }).ToClientTemplate().ToHtmlString())
                .HeaderHtmlAttributes(new { @class = HeaderSelectCheckboxClass })
                .HtmlAttributes(new { @class = SelectCheckboxClass, @data_inputParentGrid = gridName }).ClientTemplate(
                    html.KretaCheckBox(uniqueName, string.Empty, isTrue, true, new Dictionary<string, object>() { { "data-selectGroup", gridName }, { "data-rowInputName", "chk" } }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> TextBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, Expression<Func<TDataType, object>> expression, Dictionary<string, object> htmlAttr = null, int? width = null) where TDataType : class
        {
            gridBuilder.TextBoxForColumn(html, StringResourcesUtil.GetString(title), expression, htmlAttr, width);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> TextBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, Expression<Func<TDataType, object>> expression, Dictionary<string, object> htmlAttr = null, int? width = null) where TDataType : class
        {
            if (width == null)
            {
                width = 0;
            }
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width.Value)
                .Title(title)
                .ClientTemplate(
                    gridBuilder.TextBoxForColumnTemplate(html, expression, htmlAttr)
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> TextAreaForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, Expression<Func<TDataType, object>> expression, int? width = null) where TDataType : class
        {
            gridBuilder.TextAreaForColumn(html, StringResourcesUtil.GetString(title), expression, width);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> TextAreaForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, Expression<Func<TDataType, object>> expression, int? width = null) where TDataType : class
        {
            if (width == null)
            {
                width = 0;
            }
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width.Value)
                .Title(title)
                .ClientTemplate(
                    gridBuilder.TextAreaForColumnTemplate(html, expression)
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> NumericBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, Expression<Func<TDataType, object>> expression, int? min = null, int? max = null, int? precision = null, int? width = null) where TDataType : class
        {
            gridBuilder.NumericBoxForColumn(html, StringResourcesUtil.GetString(title), expression, min, max, precision, width);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> NumericBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, Expression<Func<TDataType, object>> expression, int? min = null, int? max = null, int? precision = null, int? width = null) where TDataType : class
        {
            if (width == null)
            {
                width = 0;
            }
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width.Value)
                .Title(title)
                .ClientTemplate(
                    gridBuilder.NumericBoxForColumnTemplate(html, expression, min, max, precision)
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> DropDownColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string name, int title, string url, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null) where TDataType : class
        {
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, name);
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(StringResourcesUtil.GetString(title))
                .HtmlAttributes(new { @class = DropDownClass, @data_inputParentGrid = gridName, @data_dropdownUrl = url, @data_uddlId = uniqueName }).ClientTemplate(
                    html.KretaDropdownList(uniqueName, null, dataTextField, datavalueField, groupName, groupType).HtmlAttributes(new Dictionary<string, object>() { { "data-DropdownGroup", string.Format("{0}_{1}", gridName, name) }, { "data-rowInputName", name } }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> DropDownForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, string url, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(StringResourcesUtil.GetString(title))
                .HtmlAttributes(new { @class = DropDownClass, @data_inputParentGrid = gridName, @data_dropdownUrl = url, @data_uddlId = uniqueName }).ClientTemplate(
                    html.KretaDropdownList(uniqueName, null, dataTextField, datavalueField, groupName, groupType).HtmlAttributes(new Dictionary<string, object>()
                    {
                        {"data-DropdownGroup", string.Format("{0}_{1}", gridName, proprtyName)},
                        {"value", string.Format("#:{0}#", proprtyName)},
                        {"data-rowInputName", proprtyName}
                    }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> ComboBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, string url, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null, string customClass = null, bool checkZeroValue = false, string placeholder = null) where TDataType : class
        {
            var propertyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, propertyName);
            var valueString = checkZeroValue ? string.Format(@"# if ({0} != null && {0} != 0) {{##: {0} ##}} #", propertyName)
                : string.Format(@"# if ({0} != null) {{##: {0} ##}} #", propertyName);

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .HtmlAttributes(new { @class = DropDownClass, @data_inputParentGrid = gridName, @data_dropdownUrl = url, @data_uddlId = uniqueName }).ClientTemplate(
                    html.KretaComboBox(uniqueName, url, dataTextField, datavalueField, placeholder, groupName, groupType).HtmlAttributes(new Dictionary<string, object>()
                    {
                        {"data-DropdownGroup", string.Format("{0}_{1}", gridName, propertyName)},
                        {"value", valueString},
                        {"data-rowInputName", propertyName},
                        {"class", customClass},
                    }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        [Obsolete(Core.Constants.General.Obsolete)]
        public static GridBuilder<TDataType> ComboBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, IEnumerable<SelectListItem> selectList, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null, List<string> classList = null) where TDataType : class
        {
            var propertyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{propertyName}_#=ID#";
            var classString = "";
            if (classList != null)
            {
                classString = string.Join(" ", classList);
            }
            var valueString = string.Format(@"# if ({0} != null) {{##: {0} ##}} #", propertyName);
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(StringResourcesUtil.GetString(title))
                .HtmlAttributes(new { data_inputParentGrid = gridName, data_uddlId = uniqueName }).ClientTemplate(
                    html.KretaComboBox(uniqueName, selectList, new Dictionary<string, object>
                    {
                        {"class", classString},
                        {"value", valueString},
                        {"data-rowInputName", propertyName}
                    }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> ComboBoxForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, IEnumerable<SelectListItem> selectList, Expression<Func<TDataType, object>> expression, string dataTextField = "Text", string datavalueField = "Value", string groupName = null, Type groupType = null, List<string> classList = null, int? width = null) where TDataType : class
        {
            var propertyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{propertyName}_#=ID#";
            var classString = "";
            if (classList != null)
            {
                classString = string.Join(" ", classList);
            }
            if (width == null)
            {
                width = 0;
            }
            var valueString = string.Format(@"# if ({0} != null) {{##: {0} ##}} #", propertyName);
            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width.Value)
                .Title(title)
                .HtmlAttributes(new { data_inputParentGrid = gridName, data_uddlId = uniqueName }).ClientTemplate(
                    html.KretaComboBox(uniqueName, selectList, new Dictionary<string, object>
                    {
                        {"class", classString},
                        {"value", valueString},
                        {"data-rowInputName", propertyName}
                    }).ToClientTemplate().ToHtmlString()
                ));

            return gridBuilder;
        }

        [Obsolete("Ehelyett a metódus helyet használd a string title paraméterrel rendelkező metódust!")]
        public static GridBuilder<TDataType> TimePickerForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, Expression<Func<TDataType, object>> expression, int interval = 5, DateTime? minimum = null, DateTime? maximum = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);

            var sb = new StringBuilder();
            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(html.KretaTimePicker(uniqueName, interval: interval, minValue: minimum, maxValue: maximum, htmlAttributes: new Dictionary<string, object>()
            {
                {"value", ""},
                {"data-rowInputName", proprtyName}
            }).ToClientTemplate().ToHtmlString());
            sb.Append("#} else {#");
            sb.Append(html.KretaTimePicker(uniqueName, interval: interval, minValue: minimum, maxValue: maximum, htmlAttributes: new Dictionary<string, object>()
            {
                {"value", string.Format("#:{0}#", proprtyName)},
                {"data-rowInputName", proprtyName}
            }).ToClientTemplate().ToHtmlString());
            sb.Append("#}#");

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(StringResourcesUtil.GetString(title))
                .HtmlAttributes(new { @class = TimePickerClass, @data_inputParentGrid = gridName }).ClientTemplate(sb.ToString()));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> TimePickerForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, Expression<Func<TDataType, object>> expression, int interval = 5, DateTime? minimum = null, DateTime? maximum = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = string.Format("{0}_{1}_#=ID#", gridName, proprtyName);

            var sb = new StringBuilder();
            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(html.KretaTimePicker(uniqueName, interval: interval, minValue: minimum, maxValue: maximum, htmlAttributes: new Dictionary<string, object>()
            {
                {"value", ""},
                {"data-rowInputName", proprtyName}
            }).ToClientTemplate().ToHtmlString());
            sb.Append("#} else {#");
            sb.Append(html.KretaTimePicker(uniqueName, interval: interval, minValue: minimum, maxValue: maximum, htmlAttributes: new Dictionary<string, object>()
            {
                {"value", string.Format("#:{0}#", proprtyName)},
                {"data-rowInputName", proprtyName}
            }).ToClientTemplate().ToHtmlString());
            sb.Append("#}#");

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .HtmlAttributes(new { @class = TimePickerClass, @data_inputParentGrid = gridName }).ClientTemplate(sb.ToString()));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> DatePickerForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, int title, Expression<Func<TDataType, object>> expression, DateTime? minimum = null, DateTime? maximum = null) where TDataType : class
        {
            gridBuilder.DatePickerForColumn(html, StringResourcesUtil.GetString(title), expression, minimum, maximum);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> DatePickerForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper html, string title, Expression<Func<TDataType, object>> expression, DateTime? minimum = null, DateTime? maximum = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(expression);
            var gridName = gridBuilder.ToComponent().Name;
            var uniqueName = $"{gridName}_{proprtyName}_#=ID#";

            var sb = new StringBuilder();

            sb.AppendFormat("#if(CommonUtils.isNullOrUndefined({0})){{#", proprtyName);
            sb.Append(html.KretaDatePicker(uniqueName, minValue: minimum, maxValue: maximum, htmlAttributes: new Dictionary<string, object>
            {
                {"value", ""},
                {"data-rowInputName", proprtyName}
            }).ToClientTemplate().ToHtmlString());
            sb.Append("#} else {#");
            sb.Append(html.KretaDatePicker(uniqueName, minValue: minimum, maxValue: maximum, htmlAttributes: new Dictionary<string, object>
            {
                {"value", $"#:{proprtyName}#"},
                {"data-rowInputName", proprtyName}
            }).ToClientTemplate().ToHtmlString());
            sb.Append("#}#");

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .HtmlAttributes(new { @class = TimePickerClass, data_inputParentGrid = gridName }).ClientTemplate(
                    sb.ToString()
                ));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> SelectForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper<TDataType> html, string title, Expression<Func<TDataType, object>> expression, List<SelectListItem> list, bool hasTooltip = false, int? width = null, Dictionary<string, object> additionatHeaderHtmlAttributes = null) where TDataType : class
        {
            gridBuilder.SelectForColumn(html, title, expression, list.Select(x => new ExtendedSelectListItem(x)).ToList(), hasTooltip, width, additionatHeaderHtmlAttributes);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> SelectForColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, HtmlHelper<TDataType> html, string title, Expression<Func<TDataType, object>> expression, List<ExtendedSelectListItem> list, bool hasTooltip = false, int? width = null, Dictionary<string, object> additionatHeaderHtmlAttributes = null) where TDataType : class
        {
            if (width == null)
            {
                width = 0;
            }

            var headerHtmlAttributes = new Dictionary<string, object>();
            if (additionatHeaderHtmlAttributes != null)
            {
                headerHtmlAttributes.AddRange(additionatHeaderHtmlAttributes);
            }

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Width(width.Value)
                .Title(title)
                .ClientTemplate(
                    gridBuilder.SelectForColumnTemplate(html, expression, list, hasTooltip)
                )
                .HeaderHtmlAttributes(headerHtmlAttributes));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> ConditionColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, int title, Expression<Func<TDataType, object>> conditionExpression, string trueTemplate, string falseTemplate) where TDataType : class
        {
            gridBuilder.ConditionColumn(StringResourcesUtil.GetString(title), conditionExpression, trueTemplate, falseTemplate);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> ConditionColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, string title, Expression<Func<TDataType, object>> conditionExpression, string trueTemplate, string falseTemplate) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(conditionExpression);
            var sb = new StringBuilder();
            sb.AppendFormat("#if({0}){{#", proprtyName);
            sb.Append(trueTemplate);
            sb.Append("#}else{#");
            sb.Append(falseTemplate);
            sb.Append("#}#");

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .ClientTemplate(sb.ToString()));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> ConditionColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, int title, Expression<Func<TDataType, object>> conditionExpression, string trueTemplate, string falseTemplate, int width) where TDataType : class
        {
            gridBuilder.ConditionColumn(StringResourcesUtil.GetString(title), conditionExpression, trueTemplate, falseTemplate, width);
            return gridBuilder;
        }

        public static GridBuilder<TDataType> ConditionColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, string title, Expression<Func<TDataType, object>> conditionExpression, string trueTemplate, string falseTemplate, int width, Dictionary<string, object> additionatHeaderHtmlAttributes = null) where TDataType : class
        {
            var proprtyName = GetProperyNameFromExpression(conditionExpression);
            var sb = new StringBuilder();
            sb.AppendFormat("#if({0}){{#", proprtyName);
            sb.Append(trueTemplate);
            sb.Append("#}else{#");
            sb.Append(falseTemplate);
            sb.Append("#}#");

            var headerHtmlAttributes = new Dictionary<string, object>();
            if (additionatHeaderHtmlAttributes != null)
            {
                headerHtmlAttributes.AddRange(additionatHeaderHtmlAttributes);
            }

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .ClientTemplate(sb.ToString())
                .Width(width)
                .HeaderHtmlAttributes(headerHtmlAttributes));

            return gridBuilder;
        }

        public static GridBuilder<TDataType> TemplateColumn<TDataType>(this GridBuilder<TDataType> gridBuilder, string title, string template, int width, Dictionary<string, object> additionatHeaderHtmlAttributes = null, string header = null) where TDataType : class
        {
            var stringBuilder = new StringBuilder();
            stringBuilder.Append(template);

            var headerHtmlAttributes = new Dictionary<string, object>();
            if (additionatHeaderHtmlAttributes != null)
            {
                headerHtmlAttributes.AddRange(additionatHeaderHtmlAttributes);
            }

            gridBuilder.Columns(c => c.Template(t => t.ToString())
                .Title(title)
                .ClientTemplate(stringBuilder.ToString())
                .Width(width)
                .HeaderHtmlAttributes(headerHtmlAttributes)
                .HeaderTemplate(header)
                );

            return gridBuilder;
        }

        private static string GetToolbarHtml(string gridName, HtmlHelper html, bool isPageble, int pageSizes, bool isMultipleGrid = false, bool allowExcelExport = false, bool allowPDFExport = false, string exportColumnUrl = null, string exportDataUrl = null, bool mustShowPagerCount = true, string excelExportFileName = null, bool popupExport = false)
        {
            var pagingTemplate = string.Empty;
            if (isPageble)
            {
                var itemlist = new List<SelectListItem>() { new SelectListItem { Text = "100" }, new SelectListItem { Text = "200" }, new SelectListItem { Text = "500" } };
                foreach (var item in itemlist)
                {
                    if (item.Text == pageSizes.ToString())
                        item.Selected = true;
                }
                var dropdown = html.KretaDropdownList(gridName + "_PageSize", itemlist, new Dictionary<string, object> { { "title", StringResourcesUtil.GetString(4486) } });
                pagingTemplate = string.Format(PagerToolbarTemplate, dropdown.ToHtmlString(), StringResourcesUtil.GetString(3483), StringResourcesUtil.GetString(3484), mustShowPagerCount ? "mustShowPagerCount" : "");
            }

            var excelExportTemplate = string.Empty;
            var PDFExportTemplate = string.Empty;

            if (allowExcelExport)
            {
                excelExportTemplate = string.Format(ExcelExportToolbarTemplate, StringResourcesUtil.GetString(182), gridName, excelExportFileName + ".xlsx", popupExport.ToString().ToLower());
            }

            if (allowPDFExport)
            {
                PDFExportTemplate = string.Format(PdfExportToolbarTemplate, StringResourcesUtil.GetString(4485));
            }

            string openAllGrid = string.Format(@"
                <button type=""button"" class=""k-button k-button-icontext"" title=""{0}"" href=""javascript:void(0);"" onClick=""KretaGridHelper.openAllGrid()"">
                    <span class=""k-icon k-i-kpi""></span>
                </button>", StringResourcesUtil.GetString(4487));

            return string.Format(ToolbarTemplate, pagingTemplate, excelExportTemplate, PDFExportTemplate, isMultipleGrid ? openAllGrid : string.Empty);
        }

        private static string GetProperyNameFromExpression<TDataType>(Expression<Func<TDataType, object>> expression)
        {
            try
            {
                var body = expression.Body as UnaryExpression;
                string proprtyName;
                if (body != null)
                {
                    proprtyName = ((MemberExpression)(expression.Body as UnaryExpression).Operand).Member.Name;
                }
                else
                {
                    proprtyName = ModelMetadata.FromLambdaExpression(expression, new ViewDataDictionary<TDataType>()).PropertyName;
                }
                return proprtyName;
            }
            catch
            {
                return string.Empty;
            }
        }

        public static GridBoundColumnBuilder<TFirstLevelType> SetDisplayProperty<TFirstLevelType>(this GridBoundColumnBuilder<TFirstLevelType> helper, string clientTemplateProperty) where TFirstLevelType : class
        {
            GridBoundColumnBuilder<TFirstLevelType> result = helper.ClientTemplate($@"#if ({clientTemplateProperty} == null) {{##:''##}} else {{##:{clientTemplateProperty}##}}#");
            return result;
        }

        public static GridBoundColumnBuilder<TFirstLevelType> SetDisplayPropertyWithToolip<TFirstLevelType>(this GridBoundColumnBuilder<TFirstLevelType> helper, string clientTemplateProperty, string clientTemplateTooltipProperty = null, string additionalClasses = null) where TFirstLevelType : class
        {
            var templateText = $@"#if ({clientTemplateProperty} == null) {{##:''##}} else {{##:{clientTemplateProperty}##}}#";

            string tooltipTemplateText = string.IsNullOrWhiteSpace(clientTemplateTooltipProperty) ?
                templateText :
                $@"#if ({clientTemplateTooltipProperty} == null) {{##:''##}} else {{##:{clientTemplateTooltipProperty}##}}#";

            GridBoundColumnBuilder<TFirstLevelType> result = helper
                .ClientTemplate($@"<span data-tooltiptext=""{tooltipTemplateText}"">{templateText}</span>")
                .HtmlAttributes(string.IsNullOrWhiteSpace(additionalClasses) ?
                    new { @class = "kretaEllipsis kretaTooltipDefaultClass" } :
                    new { @class = $"kretaEllipsis kretaTooltipDefaultClass {additionalClasses}" });

            return result;
        }

        public static GridBoundColumnBuilder<TFirstLevelType> SetHtmlDisplayPropertyWithToolip<TFirstLevelType>(this GridBoundColumnBuilder<TFirstLevelType> helper, string clientTemplateProperty, string tooltipClassName, string tooltipDataAttributeName, string additionalClasses = null) where TFirstLevelType : class
        {
            var templateText = $@"#if ({clientTemplateProperty} == null) {{##:''##}} else {{##={clientTemplateProperty}##}}#";

            GridBoundColumnBuilder<TFirstLevelType> result = helper
                .ClientTemplate($"<span class='kendoTooltip {tooltipClassName}' data-{tooltipDataAttributeName}='#: {clientTemplateProperty} #'>{templateText}</span>")
                .HtmlAttributes(string.IsNullOrWhiteSpace(additionalClasses) ?
                    new { @class = "kretaEllipsis " } :
                    new { @class = $"kretaEllipsis {additionalClasses}" });

            return result;
        }

        public static GridBoundColumnBuilder<TFirstLevelType> SetClientTemplateWithToolip<TFirstLevelType>(this GridBoundColumnBuilder<TFirstLevelType> helper, string clientTemplateFormat, string clientTemplateEmptyCondition, string clientTemplateTooltipFormat = null, string clientTemplateTooltipEmptyCondition = null, string additionalClasses = null) where TFirstLevelType : class
        {
            var templateText = !string.IsNullOrWhiteSpace(clientTemplateEmptyCondition) ? $@"#if ({clientTemplateEmptyCondition}) {{##:''##}} else {{#{clientTemplateFormat}#}}#" : $@"{clientTemplateFormat}";

            string tooltipTemplateText = string.IsNullOrWhiteSpace(clientTemplateTooltipFormat) ?
                templateText :
                !string.IsNullOrWhiteSpace(clientTemplateTooltipEmptyCondition) ? $@"#if ({clientTemplateTooltipEmptyCondition}) {{##:''##}} else {{#{clientTemplateTooltipFormat}#}}#" : $@"{clientTemplateTooltipFormat}";

            GridBoundColumnBuilder<TFirstLevelType> result = helper
                .ClientTemplate($@"<span data-tooltiptext=""{tooltipTemplateText}"">{templateText}</span>")
                .HtmlAttributes(string.IsNullOrWhiteSpace(additionalClasses) ?
                    new { @class = "kretaEllipsis kretaTooltipDefaultClass" } :
                    new { @class = $"kretaEllipsis kretaTooltipDefaultClass {additionalClasses}" });

            return result;
        }

        #region Formázások

        /// <summary>
        /// A dátumok formázza a gridben.
        /// </summary>
        public static string DateFormat
        {
            get { return "{0:d}"; }
        }

        public static string DateTimeFormat
        {
            get { return "{0:g}"; }
        }

        public static string DateTimeFormatLong
        {
            get { return "{0:G}"; }
        }

        public static string MoneyFormat
        {
            get { return "{0:C0}"; }
        }

        public static string NumberFormat
        {
            get { return "{0:N0}"; }
        }

        public static string TimeFormat
        {
            get { return "{0:t}"; }
        }

        public static string MoneyTemplate(string propName)
        {
            return string.Format("<#: {0} #> Ft", propName);
        }

        public static string PrecisionFormat(int precision)
        {
            return string.Format("{{0:0.{0}}}", string.Empty.PadRight(precision, '#'));
        }

        #endregion Formázások
    }
}