//using System.Linq.Expressions;
//using System.Numerics;
//using System.Reflection;

//namespace Modules.Library.Domain.Utils;

//internal abstract class OrderBaseUtil<T, TOrder> where TOrder : INumber<TOrder>
//{
//    protected abstract Expression<Func<T, TOrder>>? GetOrderPropertyExpression();
//    private readonly List<T> _items;

//    public OrderBaseUtil(List<T> items, Expression<Func<T, TOrder>> getOrderPropertyExpression)
//    {
//        _getOrderPropertyExpression = getOrderPropertyExpression;
//        _items = items;
//        _getOrderProperty = getOrderPropertyExpression.Compile();
        
//        var getOrderValueEx = Expression.Invoke(getOrderPropertyExpression, Expression.Parameter(typeof(T)));
//        _incrementOrder = Expression.Lambda<Func<T, TOrder>>(Expression.Add(getOrderValueEx, Expression.Constant(1))).Compile();
//        _decrementOrder = Expression.Lambda<Func<T, TOrder>>(Expression.Subtract(getOrderValueEx, Expression.Constant(1))).Compile();

//        var tOrderParameterEx = Expression.Parameter(typeof(TOrder));
//        _isLessThanOrEqual = Expression.Lambda<Func<T, TOrder, bool>>(Expression.LessThanOrEqual(getOrderValueEx, tOrderParameterEx)).Compile();
//        _isGraterThanOrEqual = Expression.Lambda<Func<T, TOrder, bool>>(Expression.GreaterThanOrEqual(getOrderValueEx, tOrderParameterEx)).Compile();
//    }

//    private static Func<T, TOrder> GetOrderProperty() => GetOrderPropertyExpression?.Compile() ?? throw new NotImplementedException();
//    private readonly Func<T, TOrder> _incrementOrder;
//    private readonly Func<T, TOrder> _decrementOrder;
//    private readonly Func<T, TOrder, bool> _isLessThanOrEqual;
//    private readonly Func<T, TOrder, bool> _isGraterThanOrEqual;

//    private void SetItemOrder(TOrder lastOrder, TOrder newOrder)
//    {
//        if (IsOrderOutOfRange(lastOrder)) throw new ArgumentOutOfRangeException(nameof(lastOrder));
//        if (IsOrderOutOfRange(newOrder)) throw new ArgumentOutOfRangeException(nameof(newOrder));
//        var minOrder = Min(lastOrder, newOrder);
//        var maxOrder = Max(lastOrder, newOrder);
//        var orderedItems = OrderedItemsInsideRange(minOrder, maxOrder);
//        var targetItem = orderedItems.First(q => _getOrderProperty(q) == newOrder);
//        bool seen = false;
//        for (int i = 0; i < orderedItems.Count; i++)
//        {
//            if (object.ReferenceEquals(_items[i], targetItem))
//            {
//                SetOrderValue(orderedItems[i], newOrder); //orderedItems[i].Order = newOrder;
//                seen = true;
//            }
//            //else if (seen && items[i].Order <= newOrder)
//            else if (seen && _isLessThanOrEqual(_items[i], newOrder))
//            {
//                DecrementOrder(orderedItems[i]); //orderedItems[i].Order--; // move it left
//            }
//            //else if (items[i].Order >= newOrder)
//            else if (_isGraterThanOrEqual(_items[i], newOrder))
//            {
//                IncrementOrder(orderedItems[i]); //orderedItems[i].Order++; // move it right
//            }
//        }
//    }

//    protected abstract List<T> OrderedItemsInsideRange(TOrder min, TOrder max);

//    protected abstract TOrder Max(TOrder one, TOrder another);
//    protected abstract TOrder Min(TOrder one, TOrder another);

//    protected abstract bool IsOrderOutOfRange(TOrder order);

//    private void SetOrderValue(T item, TOrder value) => item.SetPropertyValue(GetOrderPropertyExpression, value);
//    private void IncrementOrder(T item) => item.SetPropertyValue(GetOrderPropertyExpression, _incrementOrder(item));
//    private void DecrementOrder(T item) => item.SetPropertyValue(GetOrderPropertyExpression, _decrementOrder(item));
//}

//public static class LambdaExtensions
//{
//    public static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T, TValue>> memberLamda, TValue value)
//    {
//        var memberSelectorExpression = memberLamda.Body as MemberExpression;
//        if (memberSelectorExpression != null)
//        {
//            var property = memberSelectorExpression.Member as PropertyInfo;
//            if (property != null)
//            {
//                property.SetValue(target, value, null);
//            }
//        }
//    }
//}
