using System;
using System.Diagnostics.CodeAnalysis;
using InABox.Core;

namespace InABox.DynamicGrid
{
    public interface IDynamicEditorForm
    {
        
        event OnBeforeLoad OnBeforeLoad; 
        void BeforeLoad();
        
        event OnAfterLoad OnAfterLoad;
        void AfterLoad();
        
        event OnValidateData? OnValidateData;

        OnCustomiseColumns? OnCustomiseColumns { set; }
        OnDefineLookupFilter? OnDefineFilter { set; }

        OnDefineLookup? OnDefineLookups { set; }

        DefineEditorEventHandler? OnDefineEditor { set; }
        event OnFormCustomiseEditor? OnFormCustomiseEditor;
        OnReconfigureEditors? OnReconfigureEditors { set; }
        event OnCreateEditorControl? OnCreateEditorControl;

        event OnAfterEditorValueChanged? OnAfterEditorValueChanged;
        event EditorValueChangedHandler? OnEditorValueChanged;

        event OnSelectPage? OnSelectPage;
        DynamicGridSaveEvent? OnSaveItem { set; }

        DynamicEditorPages? Pages { get; }

        delegate void OnReloadEventHandler(IDynamicEditorForm form);
        event OnReloadEventHandler? OnReload;

        bool ReadOnly { get; set; }

        BaseObject[] Items { get; set; }

        void Setup(Type type, DynamicEditorPages? pages = null, DynamicEditorButtons? buttons = null,
            Func<Type, CoreTable?>? pageDataHandler = null, bool preloadPages = false);

        bool TryFindEditor(string columnname, [NotNullWhen(true)] out IDynamicEditorControl? editor);

        object? GetEditorValue(string columnName);
        void SetEditorValue(string columnName, object? value);

        void SetLayoutType<T>() where T : DynamicEditorGridLayout;

        void SetLayout(DynamicEditorGridLayout layout);

        void UnloadEditorPages(bool saved);
    }

    public static class DynamicEditorFormExtensions
    {
        public static bool TryFindEditor<TEditor>(this IDynamicEditorForm form, string columnname, [NotNullWhen(true)] out TEditor? editor)
            where TEditor : BaseDynamicEditorControl
        {
            if(form.TryFindEditor(columnname, out var control) && control is TEditor editorControl)
            {
                editor = editorControl;
                return true;
            }
            else
            {
                editor = null;
                return false;
            }
        }

        public static IDynamicEditorControl? FindEditor(this IDynamicEditorForm form, string columnName)
        {
            form.TryFindEditor(columnName, out var editor);
            return editor;
        }
        public static TEditor? FindEditor<TEditor>(this IDynamicEditorForm form, string columnName)
            where TEditor : BaseDynamicEditorControl
        {
            form.TryFindEditor<TEditor>(columnName, out var editor);
            return editor;
        }
    }
}