using System.Linq.Expressions;
using System.Reflection;

namespace Tiobon.Core.Common.DB.Dapper.Extensions;

public static class LambdaExtensions
{
    /// <summary>
    /// 获取对象表达式指定属性的值
    /// 如获取:Out_Scheduling对象的ID或基他字段
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="expression">格式 Expression<Func<Out_Scheduling, object>>sch=x=>new {x.v1,x.v2} or x=>x.v1 解析里面的值返回为数组</param>
    /// <returns></returns>
    public static string[] GetExpressionToArray<TEntity>(this Expression<Func<TEntity, object>> expression)
    {
        string[] propertyNames = null;
        if (expression.Body is MemberExpression)
        {
            propertyNames = new string[] { ((MemberExpression)expression.Body).Member.Name };
        }
        else
        {
            propertyNames = expression.GetExpressionProperty().Distinct().ToArray();
        }
        return propertyNames;
    }

    /// <summary>
    /// 属性判断待完
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static IEnumerable<PropertyInfo> GetGenericProperties(this Type type)
    {
        return type.GetProperties().GetGenericProperties();
    }
    /// <summary>
    /// 属性判断待完
    /// </summary>
    /// <param name="properties"></param>
    /// <returns></returns>
    public static IEnumerable<PropertyInfo> GetGenericProperties(this IEnumerable<PropertyInfo> properties)
    {
        return properties.Where(x => !x.PropertyType.IsGenericType && x.PropertyType.GetInterface("IList") == null || x.PropertyType.GetInterface("IEnumerable", false) == null);
    }
}

public class ParameterRebinder : ExpressionVisitor
{

    private readonly Dictionary<ParameterExpression, ParameterExpression> map;
    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
    {
        this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    }

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
    {
        return new ParameterRebinder(map).Visit(exp);
    }
}
