private static int TreeViewRec <VM, T> (
            StringBuilder sb,
            StringBuilder sbInit,
            bool editMode,
            HtmlHelper <VM> htmlHelper,
            RenderInfo <IEnumerable <T> > renderInfo,
            Func <int, string> collectionName,
            ExternalContainerType itemContainer,
            string rootClass,
            object[] itemTemplates,
            Func <object, int, int> itemTemplateSelector,
            Func <int, string> itemClassSelector,
            Func <object, int, TreeViewItemStatus> itemStatus,
            float opacity,
            bool canMove,
            int level,
            int totalCount,
            string fatherName,
            string root_id)
        {
            string basicId = BasicHtmlHelper.IdFromName(fatherName);



            sbInit.Append(renderInfo.PartialRendering);

            IDictionary <string, object> htmlAttributesContainer = new Dictionary <string, object>();

            string externalOpenTag  = null;
            string externalCloseTag = null;
            string handleClass      = basicId + "_handle";

            htmlAttributesContainer["id"] = basicId + "_ItemsContainer";
            if (level == 0)
            {
                htmlAttributesContainer["class"] = rootClass + "  mvcct-items-container";
                rootClass = null;
            }
            else
            {
                if (rootClass != null)
                {
                    htmlAttributesContainer["class"] = rootClass + "_  mvcct-items-container";
                }
            }
            BasicHtmlHelper.GetContainerTags(ExternalContainerType.ul, htmlAttributesContainer, out externalOpenTag, out externalCloseTag);
            sb.Append(externalOpenTag);

            IEnumerable list = renderInfo.Model as IEnumerable;

            if (list == null)
            {
                list = new List <T>();
            }

            string javasctiptOpacity = string.Empty;
            int    sonIndex          = -1;;

            foreach (object o in list)
            {
                if (o == null)
                {
                    continue;
                }
                totalCount++;
                sonIndex++;
                int    templateIndex   = itemTemplateSelector(o, level);
                object initialTemplate = itemTemplates[templateIndex];
                string initCollection  = collectionName(templateIndex);


                TreeViewItemStatus status = itemStatus(o, level);
                if (initCollection == null)
                {
                    status = TreeViewItemStatus.Hide;
                }
                ITreeViewNodeContainer wrapper  = null;
                IUpdateModel           uWrapper = null;
                bool closed = isClosed(status, o, htmlHelper);
                Type type   = TemplateInvoker <string> .ExtractModelType(initialTemplate);

                if (editMode)
                {
                    wrapper =
                        typeof(TreeViewUpdater <string>).GetGenericTypeDefinition()
                        .MakeGenericType(new Type[] { type })
                        .GetConstructor(new Type[0])
                        .Invoke(new object[0]) as ITreeViewNodeContainer;
                    uWrapper = wrapper as IUpdateModel;
                    uWrapper.ImportFromModel(o, null, null, new object[] { closed });
                }
                else
                {
                    wrapper  = new TreeViewUpdater <T>(false);
                    uWrapper = wrapper as IUpdateModel;
                }



                string prefix        = renderInfo.Prefix;
                string partialPrefix = renderInfo.PartialPrefix;
                if (editMode)
                {
                    sbInit.Append(
                        BasicHtmlHelper.RenderUpdateInfoI(htmlHelper, uWrapper, ref partialPrefix, new string[0]));
                }
                else
                {
                    BasicHtmlHelper.RenderUpdateInfoI(htmlHelper, uWrapper, ref partialPrefix, new string[0], noOutput: true);
                }
                prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);
                if (level == 0)
                {
                    wrapper.FatherOriginalId = null;
                }
                else
                {
                    wrapper.FatherOriginalId = fatherName;
                }
                wrapper.OriginalId        = prefix;
                wrapper.PositionAsSon     = sonIndex;
                wrapper.SonNumber         = 0;
                wrapper.SonCollectionName = null;
                string itemOpenTag  = null;
                string itemCloseTag = null;

                string innerItemOpenTag  = null;
                string innerItemCloseTag = null;

                htmlAttributesContainer["id"]    = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "Container"));
                htmlAttributesContainer["class"] = closed ? "closed" : "open";
                BasicHtmlHelper.GetContainerTags(ExternalContainerType.li, htmlAttributesContainer, out itemOpenTag, out itemCloseTag);

                htmlAttributesContainer["id"]    = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item_SubContainer"));
                htmlAttributesContainer["class"] = handleClass;
                BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesContainer, out innerItemOpenTag, out innerItemCloseTag);


                bool         hasCollection = true;
                string       name          = initCollection;
                PropertyInfo property      = null;
                if (name == null)
                {
                    hasCollection = false;
                }
                else
                {
                    property      = o.GetType().GetProperty(name);
                    hasCollection = typeof(IEnumerable).IsAssignableFrom(property.PropertyType);
                }
                sb.Append(itemOpenTag);

                if (canMove && hasCollection)
                {
                    sb.Append(string.Format("<input  type='checkbox' class ='level-select_{0} level-select' />", root_id));
                }
                sb.Append(innerItemOpenTag);
                sb.Append(
                    (typeof(TemplateInvoker <string>)
                     .GetGenericTypeDefinition()
                     .MakeGenericType(new Type[] { type })
                     .GetConstructor(new Type[] { typeof(object) })
                     .Invoke(new object[] { initialTemplate }) as ITemplateInvoker)
                    .Invoke(htmlHelper, o, BasicHtmlHelper.AddField(prefix, "$.Item")));
                sb.Append(innerItemCloseTag);

                if (hasCollection)
                {
                    string currItemClass = itemClassSelector == null ?
                                           null :
                                           itemClassSelector(templateIndex);
                    if (currItemClass != null)
                    {
                        currItemClass = currItemClass.Trim() + "_" + BasicHtmlHelper.IdFromName(renderInfo.Prefix);
                    }
                    ICollection innerItem   = property.GetValue(o, new object[0]) as ICollection;
                    Type        listType    = property.PropertyType.GetGenericArguments()[0];
                    Type        allListType = typeof(IEnumerable <string>).GetGenericTypeDefinition().MakeGenericType(listType);
                    if (innerItem == null)
                    {
                        innerItem = allListType.GetConstructor(new Type[0]).Invoke(new object[0]) as ICollection;
                    }
                    wrapper.SonNumber         = innerItem.Count;
                    wrapper.SonCollectionName = initCollection;
                    if (editMode)
                    {
                        RenderWrapper <VM>(htmlHelper, partialPrefix, wrapper, sbInit);
                    }

                    totalCount = (int)typeof(TreeViewHelpers).GetMethod("TreeViewRec", BindingFlags.Static | BindingFlags.NonPublic).
                                 MakeGenericMethod(new Type[] { typeof(VM), listType })
                                 .Invoke(null, new object[]
                                         { sb,
                                           sbInit,
                                           editMode,
                                           htmlHelper,
                                           typeof(RenderInfo <string>).GetGenericTypeDefinition().MakeGenericType(allListType)
                                           .GetConstructor(new Type[] { typeof(string), typeof(string), typeof(string), allListType })
                                           .Invoke
                                               (new object[] {
                            renderInfo.Prefix,
                            renderInfo.PartialPrefix,
                            string.Empty,
                            innerItem
                        }),
                                           collectionName,
                                           itemContainer,
                                           currItemClass,
                                           itemTemplates,
                                           itemTemplateSelector,
                                           itemClassSelector,
                                           itemStatus,
                                           opacity,
                                           canMove,
                                           level + 1,
                                           totalCount,
                                           prefix,
                                           root_id });
                }
                else
                {
                    if (editMode)
                    {
                        RenderWrapper <VM>(htmlHelper, partialPrefix, wrapper, sbInit);
                    }
                }
                sb.Append(itemCloseTag);
            }


            if (canMove)
            {
                if (opacity > 1f)
                {
                    opacity = 1f;
                }
                else if (opacity < 0.01f)
                {
                    opacity = 0.01f;
                }

                if (opacity < 1f)
                {
                    javasctiptOpacity = string.Format(" opacity: {0}, ", opacity.ToString(CultureInfo.InvariantCulture));
                }
                string javascriptRootClass = string.Empty;
                if (rootClass != null)
                {
                    javascriptRootClass = string.Format(" connectWith: '.{0}', ", rootClass);
                }
                if (level > 0)
                {
                    sbInit.Append(string.Format(startScriptFormat,
                                                basicId,
                                                javasctiptOpacity,
                                                javascriptRootClass,
                                                root_id));
                }
            }
            else
            {
                if (level > 0)
                {
                    sbInit.Append(string.Format(startScriptNoMoveFormat,
                                                basicId,
                                                root_id));
                }
            }
            sb.Append(externalCloseTag);


            return(totalCount);
        }