using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using InABox.Clients;
using InABox.Core;

namespace InABox.DynamicGrid
{
    public class DynamicManyToManyDataGrid<TManyToMany, TThis> : DynamicManyToManyGrid<TManyToMany, TThis>
        where TManyToMany : Entity, IPersistent, IRemotable, new() where TThis : Entity, IRemotable, IPersistent, new()
    {
        private readonly PropertyInfo prop;

        public DynamicManyToManyDataGrid()
        {
            prop = CoreUtils.PropertyList(typeof(TManyToMany), p => p.PropertyType.IsSubclassOf(typeof(EntityLink<TThis>))).FirstOrDefault()
                ?? throw new Exception($"No EntityLink property to link entities for DynamicManyToManyGrid<{typeof(TManyToMany)},{typeof(TThis)}>");
        }

        public Guid ID { get; set; }

        protected override Guid[] CurrentGuids()
        {
            var result = new List<Guid>();
            foreach (var row in Data.Rows)
            {
                var guid = row.Get<Guid>(otherproperty.Name + ".ID");
                result.Add(guid);
            }

            return result.ToArray();
        }

        public override TManyToMany CreateItem()
        {
            var result = base.CreateItem();
            var link = prop.GetValue(result) as IEntityLink;
            if (link is null)
                throw new Exception($"Property {prop.Name} of {typeof(TManyToMany)} is null");
            link.ID = ID;
            return result;
        }

        protected override void Reload(
            Filters<TManyToMany> criteria, Columns<TManyToMany> columns, ref SortOrder<TManyToMany>? sort, 
            CancellationToken token, Action<CoreTable?, Exception?> action)
        {
            var expr = CoreUtils.CreateLambdaExpression<TManyToMany>(prop.Name + ".ID");
            criteria.Add(new Filter<TManyToMany>(expr).IsEqualTo(ID));
            Client.Query(criteria.Combine(), columns, sort, null, action);
        }

        public override TManyToMany LoadItem(CoreRow row)
        {
            var id = row.Get<TManyToMany, Guid>(x => x.ID);
            return Client
                .Query(
                    new Filter<TManyToMany>(x => x.ID).IsEqualTo(id),
                    DynamicGridUtils.LoadEditorColumns(DataColumns()))
                .ToObjects<TManyToMany>().FirstOrDefault() ?? throw new Exception($"{typeof(TManyToMany)} with ID {id} does not exist!");
        }

        public override void DeleteItems(params CoreRow[] rows)
        {
            var items = LoadItems(rows);
            foreach (var item in items)
                Client.Delete(item, "");
        }

        public override void SaveItem(TManyToMany item)
        {
            Client.Save(item, "");
        }
    }
}