using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace IRaCIS.Core.Infrastructure.Extention
{
    public static class ListTreeExtensions
    {
        /// <summary>
        /// 将列表转换为树形结构
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="list">数据</param>
        /// <param name="rootWhere">根条件</param>
        /// <param name="childsWhere">节点条件</param>
        /// <param name="addChilds">添加子节点</param>
        /// <param name="childEntity"></param>
        /// <returns></returns>
        public static List<T> ToTree<T,Tkey>(this List<T> list, Func<T, T, bool> rootWhere, Func<T, T, bool> childsWhere, Action<T, IEnumerable<T>> addChilds, Func<T, Tkey> orderSelector, T childEntity = default)
        {
            if (rootWhere is null)
            {
                throw new ArgumentNullException(nameof(rootWhere));
            }

            if (childsWhere is null)
            {
                throw new ArgumentNullException(nameof(childsWhere));
            }

            if (addChilds is null)
            {
                throw new ArgumentNullException(nameof(addChilds));
            }

            if (orderSelector is null)
            {
                throw new ArgumentNullException(nameof(orderSelector));
            }

            var treelist = new List<T>();
            //空树
            if (list == null || list.Count == 0)
            {
                return treelist;
            }
            if (!list.Any(e => rootWhere(childEntity, e)))
            {
                return treelist;
            }
            //树根
            if (list.Any(e => rootWhere(childEntity, e)))
            {
                treelist.AddRange(list.Where(e => rootWhere(childEntity, e)).OrderBy(orderSelector));
            }
            //树叶 item 是根
            foreach (var item in treelist)
            {
                if (list.Any(e => childsWhere(item, e)))
                {
                    var nodedata = list.Where(e => childsWhere(item, e)).OrderBy(orderSelector).ToList();

                    foreach (var child in nodedata)
                    {
                        //添加子集
                        var data = list.ToTree(childsWhere, childsWhere, addChilds, orderSelector, child);

                        addChilds(child, data);
                    }
                    addChilds(item, nodedata);
                }
            }
            return treelist;
        }
    }
}