using Microsoft.UI.Xaml.Controls;
using Sonex.Client.Pages;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Sonex.Client.Controls.DataGridView
{
    public sealed partial class DataGridView
    {
        public static class DynamicFilterRuntime
        {
            private static readonly MethodInfo QueryableCast =
                typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static)
                    .Where(m => m.Name == nameof(Queryable.Cast))
                    .Where(m => m.IsGenericMethodDefinition)
                    .Where(m =>
                    {
                        var p = m.GetParameters();
                        return p.Length == 1 && p[0].ParameterType == typeof(IQueryable);
                    })
                    .Single();

            // bierzemy NIE-generyczne Where(IQueryable, string, object[])
            private static readonly MethodInfo DynamicWhere =
                typeof(DynamicQueryableExtensions).GetMethods(BindingFlags.Public | BindingFlags.Static)
                    .Where(m => m.Name == nameof(DynamicQueryableExtensions.Where))
                    .Where(m => !m.IsGenericMethodDefinition)
                    .Where(m =>
                    {
                        var p = m.GetParameters();
                        return p.Length == 3
                               && p[0].ParameterType == typeof(IQueryable)
                               && p[1].ParameterType == typeof(string)
                               && p[2].ParameterType == typeof(object[]);
                    })
                    .Single();

            public static List<object> ApplyWhereToList(
                IList items,
                Type itemType,
                string predicate,
                params object[] args)
            {
                IQueryable q = items.Cast<object>().AsQueryable();

                // Cast<itemType>(IQueryable)
                q = (IQueryable)QueryableCast.MakeGenericMethod(itemType)
                    .Invoke(null, new object[] { q })!;

                // Where(IQueryable, string, object[])
                q = (IQueryable)DynamicWhere.Invoke(null, new object[] { q, predicate, args })!;

                return q.Cast<object>().ToList();
            }
        }

    }
}
