using InABox.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace InABox.Core
{
    public class SetNullData
    {
        public Guid EntityID { get; set; }

        public Guid ParentID { get; set; }

        public string Property { get; set; }

        public SetNullData(Guid entityID, string property, Guid parentID)
        {
            EntityID = entityID;
            ParentID = parentID;
            Property = property;
        }
    }

    public class DeletionData
    {
        public Dictionary<string, List<SetNullData>> SetNulls { get; set; } = new Dictionary<string, List<SetNullData>>();

        public Dictionary<string, CoreTable> Cascades { get; set; } = new Dictionary<string, CoreTable>();

        public static IColumns DeletionColumns(Type T)
        {
            var columns = Columns.None(T);
            foreach(var property in DatabaseSchema.Properties(T).Where(x => x.IsDBColumn))
            {
                columns.Add(property);
            }
            return columns;
        }
        public static Columns<T> DeletionColumns<T>() => (DeletionColumns(typeof(T)) as Columns<T>)!;

        public void DeleteEntity<T>(T entity)
            where T : Entity, new()
        {
            var entityName = typeof(T).EntityName();
            if(!Cascades.TryGetValue(entityName, out var table))
            {
                table = new CoreTable();
                table.LoadColumns(DeletionColumns<T>());
                Cascades.Add(entityName, table);
            }
            table.LoadRow(entity);
        }
        public void DeleteEntity<T>(CoreRow row)
            where T : Entity, new()
        {
            var entityName = typeof(T).EntityName();
            if(!Cascades.TryGetValue(entityName, out var table))
            {
                table = new CoreTable();
                table.LoadColumns(DeletionColumns<T>());
                Cascades.Add(entityName, table);
            }
            table.LoadRows(new CoreRow[] { row });
        }

        public void SetNullEntity<T>(Guid entityID, string property, Guid parentID)
            where T : Entity, new()
        {
            var entityName = typeof(T).EntityName();
            if (!SetNulls.TryGetValue(entityName, out var list))
            {
                list = new List<SetNullData>();
                SetNulls.Add(entityName, list);
            }
            list.Add(new SetNullData(entityID, property, parentID));
        }
    }

    // A Deletion is not IRemotable; *no one* but the database should know about it.
    public class Deletion : Entity, ILicense<CoreLicense>, IPersistent
    {
        [DateTimeEditor(Editable = Editable.Disabled)]
        public DateTime DeletionDate { get; set; }

        [TextBoxEditor(Editable = Editable.Disabled)]
        public string DeletedBy { get; set; }

        [TextBoxEditor(Editable = Editable.Disabled)]
        public string HeadTable { get; set; }

        [TextBoxEditor(Editable = Editable.Disabled)]
        public string Description { get; set; }

        [NullEditor]
        public string Data { get; set; }

    }
}
