using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using InABox.Core;
using Syncfusion.Windows.Shared;

namespace InABox.DynamicGrid
{
    public static class DynamicEditorControlFactory
    {

        private static Dictionary<Type, Type>? _editors;

        private static Dictionary<Type, Type> GetEditors()
        {
            if(_editors is null)
            {
                _editors = [];
                foreach(var type in CoreUtils.TypeList(AppDomain.CurrentDomain.GetAssemblies(),
                    x => x.IsClass
                        && !x.IsAbstract
                        && !x.IsGenericType
                        && x.IsSubclassOfRawGeneric(typeof(BaseDynamicEditorControl<>))))
                {
                    var baseClass = type.GetSuperclassDefinition(typeof(BaseDynamicEditorControl<>))!;
                    var editor = baseClass.GenericTypeArguments[0];
                    if (editor == typeof(IBaseEditor) || editor.HasInterface<IBaseEditor>())
                    {
                        _editors[editor] = type;
                    }
                }
            }
            return _editors;
        }

        private static bool GetControlType(Type editorType, [NotNullWhen(true)] out Type? TControl)
        {
            var controls = GetEditors().Where(x => editorType == x.Key || editorType.IsAssignableTo(x.Key));

            Type? editType = null;
            TControl = null;
            foreach(var control in controls)
            {
                if(control.Key == editorType)
                {
                    TControl = control.Value;
                    return true;
                }
                if(TControl is null || editType!.IsAssignableTo(control.Key))
                {
                    (editType, TControl) = control;
                }
            }

            return TControl is not null;
        }

        public static BaseDynamicEditorControl? CreateControl(BaseEditor editor, IDynamicEditorHost host) 
        {
            if (GetControlType(editor.GetType(), out var TControl))
            {
                var result = Activator.CreateInstance(TControl) as BaseDynamicEditorControl;
                if (result != null)
                {
                    result.Host = host;
                    result.EditorDefinition = editor;
                }

                return result;
            }

            return null;
        }
        
    }
}