/// <summary>
        /// Converts a legacy XmlTreeNode to a new TreeNode
        /// </summary>
        /// <param name="parentId"></param>
        /// <param name="xmlTreeNode"></param>
        /// <param name="urlHelper"></param>
        /// <param name="currentSection"></param>
        /// <param name="currentQueryStrings">
        /// The current query strings for the request - this is used to append the query strings to the menu URL of the item being rendered since the menu
        /// actually belongs to this same node (request) the query strings need to exist so the menu can be rendered in some cases.
        /// </param>
        /// <param name="isRoot"></param>
        /// <returns></returns>
        internal static TreeNode ConvertFromLegacy(string parentId, XmlTreeNode xmlTreeNode, UrlHelper urlHelper, string currentSection, FormDataCollection currentQueryStrings, bool isRoot = false)
        {
            //  /umbraco/tree.aspx?rnd=d0d0ff11a1c347dabfaa0fc75effcc2a&id=1046&treeType=content&contextMenu=false&isDialog=false

            //we need to convert the node source to our legacy tree controller
            var childNodesSource = urlHelper.GetUmbracoApiService<LegacyTreeController>("GetNodes");

            var childQuery = (xmlTreeNode.Source.IsNullOrWhiteSpace() || xmlTreeNode.Source.IndexOf('?') == -1)
                ? ""
                : xmlTreeNode.Source.Substring(xmlTreeNode.Source.IndexOf('?'));

            //append the query strings
            childNodesSource = childNodesSource.AppendQueryStringToUrl(childQuery);

            //for the menu source we need to detect if this is a root node since we'll need to set the parentId and id to -1
            // for which we'll handle correctly on the server side.            
            //if there are no menu items, then this will be empty
            var menuSource = "";
            if (xmlTreeNode.Menu != null && xmlTreeNode.Menu.Any())
            {
                menuSource = urlHelper.GetUmbracoApiService<LegacyTreeController>("GetMenu");
                //these are the absolute required query strings
                var menuQueryStrings = new Dictionary<string, object>
                    {
                        {"id", (isRoot ? "-1" : xmlTreeNode.NodeID)},
                        {"treeType", xmlTreeNode.TreeType},
                        {"parentId", (isRoot ? "-1" : parentId)},
                        {"section", currentSection}
                    };
                //append the extra ones on this request
                foreach (var i in currentQueryStrings.Where(x => menuQueryStrings.Keys.Contains(x.Key) == false))
                {
                    menuQueryStrings.Add(i.Key, i.Value);
                }
                
                menuSource = menuSource.AppendQueryStringToUrl(menuQueryStrings.ToQueryString());    
            }
            

            //TODO: Might need to add stuff to additional attributes

            var node = new TreeNode(xmlTreeNode.NodeID, isRoot ? null : parentId, childNodesSource, menuSource)
            {
                HasChildren = xmlTreeNode.HasChildren,
                Icon = xmlTreeNode.Icon,
                Name = xmlTreeNode.Text,
                NodeType = xmlTreeNode.NodeType
            };
            if (isRoot)
            {
                node.AdditionalData.Add("treeAlias", xmlTreeNode.TreeType);
            }

            //This is a special case scenario, we know that content/media works based on the normal Belle routing/editing so we'll ensure we don't
            // pass in the legacy JS handler so we do it the new way, for all other trees (Currently, this is a WIP), we'll render
            // the legacy js callback,.
            var knownNonLegacyNodeTypes = new[] { "content", "contentRecycleBin", "mediaRecyleBin", "media" };
            if (knownNonLegacyNodeTypes.InvariantContains(xmlTreeNode.NodeType) == false)
            {
                node.AssignLegacyJsCallback(xmlTreeNode.Action);
            }
            return node;
        }