#define scrolling
//#define newgrid

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using InABox.Core;
using Syncfusion.Data;

namespace InABox.DynamicGrid;


public enum DynamicGridButtonPosition
{
    Left,
    Right
}


public interface IDynamicGrid
{
    bool IsReady { get; }

    Thickness Margin { get; set; }

    DynamicGridColumns MasterColumns { get; }
    DynamicGridColumns VisibleColumns { get; }
    DynamicActionColumns ActionColumns { get; }

    CoreTable Data { get; set; }
    CoreRow[] SelectedRows { get; set; }

    double RowHeight { get; set; }
    double HeaderHeight { get; set; }

    double FontSize { get; set; }
    void Refresh(bool columns, bool data);

    void DoChanged();

    void InitialiseEditorForm(IDynamicEditorForm editor, object[] items, Func<Type, CoreTable>? pageDataHandler = null, bool preloadPages = false);
    bool EditItems(object[] items, Func<Type, CoreTable?>? PageDataHandler = null, bool PreloadPages = false);

    //bool DirectEdit(CoreTable data);

    event OnFilterRecord OnFilterRecord;
    event OnCreateItem OnCreateItem;

    event OnDoubleClick? OnDoubleClick;

    delegate void ReconfigureEvent(DynamicGridOptions options);
    event ReconfigureEvent? OnReconfigure;

    public abstract void Reconfigure();

    /// <summary>
    /// Add <paramref name="onReconfigure"/> to <see cref="OnReconfigure"/>, and then call <see cref="Reconfigure"/>.
    /// </summary>
    /// <remarks>
    /// Probably should only be called once per grid, otherwise there will be multiple event handlers bound.<br/>
    /// If you want to reconfigure without specifiying
    /// a new reconfigure event, use <see cref="Reconfigure"/>.
    /// </remarks>
    /// <param name="onReconfigure"></param>
    public void Reconfigure(ReconfigureEvent onReconfigure);

    public DynamicGridOptions Options { get; }

    void AddVisualFilter(string column, string value, FilterType filtertype = FilterType.Contains);

    Button AddButton(string? caption, BitmapImage? image, string? tooltip, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left);

    Button AddButton(string? caption, BitmapImage? image, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left);

    void UpdateButton(Button button, BitmapImage? image, string? text, string? tooltip = null);

    event OnDefineFilter OnDefineFilter;

    event OnPrintData OnPrintData;

    event BeforeRefreshEventHandler BeforeRefresh;
    
    event AfterRefreshEventHandler AfterRefresh;
    
    event EntitySaveEvent? OnAfterSave;
    event EntitySaveEvent? OnBeforeSave;

    int DesiredWidth();

    void AddHiddenColumn(string column);

    void UpdateRow<TType>(CoreRow row, string column, TType value, bool refresh = true);

    void UpdateRow<T, TType>(CoreRow row, Expression<Func<T, TType>> column, TType value, bool refresh = true);
}

public interface IDynamicGrid<T> : IDynamicGrid
    where T : BaseObject, new()
{
    T CreateItem();

    T LoadItem(CoreRow row);

    void SaveItem(T item);

    void SaveItems(T[] items);

    void DeleteItems(CoreRow[] rows);

    bool EditItems(T[] items, Func<Type, CoreTable?>? PageDataHandler = null, bool PreloadPages = false);
}