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

namespace InABox.Core
{
    internal class ParameterReplacer : ExpressionVisitor
    {
        private readonly ParameterExpression _parameter;

        internal ParameterReplacer(ParameterExpression parameter)
        {
            _parameter = parameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return base.VisitParameter(_parameter);
        }
    }

    public static class IQueryableExtensions
    {
        public static IOrderedQueryable<T> SortBy<T>(this IQueryable<T> source, Expression property)
        {
            return source.OrderBy(ToLambda<T>(property));
        }

        public static IOrderedQueryable<T> SortByDescending<T>(this IQueryable<T> source, Expression property)
        {
            return source.OrderByDescending(ToLambda<T>(property));
        }

        public static Expression<Func<T, object>> ToLambda<T>(Expression property)
        {
            //var type = typeof(T);
            //var body = property;
            //var parameter = Expression.Parameter(type,"x");
            //var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(Object));
            //dynamic lambda = Expression.Lambda(delegateType, body, parameter);
            //dynamic comp = lambda.Compile();
            //return comp;

            var paramExpr = Expression.Parameter(typeof(T));
            var exprBody = Expression.Convert(property, typeof(object));
            var replBody = new ParameterReplacer(paramExpr).Visit(exprBody);
            var finalExpr = Expression.Lambda<Func<T, object>>(replBody, paramExpr);
            return finalExpr;
        }
    }
}