using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using InABox.Core;
using NPOI.OpenXmlFormats.Wordprocessing;
using Syncfusion.UI.Xaml.Grid;
using Syncfusion.UI.Xaml.TreeGrid;

namespace InABox.DynamicGrid;

public abstract class DynamicGridEditorColumn<TEditor, TGridColumn, TTreeColumn> : IDynamicGridEditorColumn
    where TEditor : class
    where TGridColumn : GridColumn, new()
    where TTreeColumn : TreeGridColumn, new()
{
    
    public List<string> ExtraColumns { get; } = new();
    
    public string MappingName => Definition.ColumnName.Replace('.', '_');

    public string TreeMappingName => $"[{Definition.ColumnName}]";

    public event DynamicColumnEntityChangedEvent? EntityChanged;

    public void DoEntityChanged(string columnname, Dictionary<string, object?> changes)
    {
        EntityChanged?.Invoke(this, new(columnname, changes));
    }

    public TGridColumn CreateGridColumn()
    {
        var column = new TGridColumn()
        {
            UpdateTrigger = UpdateSourceTrigger.PropertyChanged
        };
        UpdateBinding(column);
        if(Editor is not null)
        {
            DoConfigure(column, Editor);
        }
        return column;
    }

    GridColumn IDynamicGridEditorColumn.CreateGridColumn() => CreateGridColumn();

    public TTreeColumn CreateTreeGridColumn()
    {
        var column = new TTreeColumn()
        {
            UpdateTrigger = UpdateSourceTrigger.PropertyChanged
        };
        UpdateBinding(column);
        if(Editor is not null)
        {
            DoConfigure(column, Editor);
        }
        return column;
    }

    TreeGridColumn IDynamicGridEditorColumn.CreateTreeGridColumn() => CreateTreeGridColumn();

    public virtual void UpdateUIComponent(IDynamicGridGridUIComponent component)
    {
    }

    protected DynamicGridEditorColumn(DynamicGridColumn definition)
    {
        Definition = definition;
    }
    
    public DynamicGridColumn Definition { get; set; }

    public virtual IDynamicGridSummary? Summary() => null;

    public TEditor? Editor
    {
        get
        {
            if (Definition.Editor is not TEditor result)
            {
                result = null;
                // result = CoreUtils.GetProperty<TEntity>(Definition.ColumnName)?.GetEditor() as TEditor;
            }
            return result;
        }
    }

    protected virtual void UpdateBinding(TGridColumn column)
    {
        column.MappingName = MappingName;
    }
    protected virtual void UpdateBinding(TTreeColumn column)
    {
        column.MappingName = TreeMappingName;
    }

    protected TextAlignment GetTextAlignment(TEditor editor) => Definition.Alignment == Alignment.NotSet
        ? editor is NumericEditor ? TextAlignment.Right : TextAlignment.Left
        : Definition.Alignment == Alignment.BottomLeft || 
          Definition.Alignment == Alignment.MiddleLeft || 
          Definition.Alignment == Alignment.TopLeft
            ? TextAlignment.Left
            : Definition.Alignment == Alignment.BottomCenter ||
              Definition.Alignment == Alignment.MiddleCenter ||
              Definition.Alignment == Alignment.TopCenter
                ? TextAlignment.Center
                : TextAlignment.Right;
    
    
    protected HorizontalAlignment GetHorizontalAlignment(TEditor editor) => Definition.Alignment == Alignment.NotSet
        ? editor is NumericEditor ? HorizontalAlignment.Right : HorizontalAlignment.Left
        : Definition.Alignment == Alignment.BottomLeft || 
          Definition.Alignment == Alignment.MiddleLeft || 
          Definition.Alignment == Alignment.TopLeft
            ? HorizontalAlignment.Left
            : Definition.Alignment == Alignment.BottomCenter ||
              Definition.Alignment == Alignment.MiddleCenter ||
              Definition.Alignment == Alignment.TopCenter
                ? HorizontalAlignment.Center
                : HorizontalAlignment.Right;

    protected VerticalAlignment GetVerticalAlignment(TEditor editor) => Definition.Alignment == Alignment.NotSet
        ? VerticalAlignment.Center
        : Definition.Alignment == Alignment.TopLeft ||
          Definition.Alignment == Alignment.TopCenter ||
          Definition.Alignment == Alignment.TopRight
            ? VerticalAlignment.Top
            : Definition.Alignment == Alignment.MiddleLeft ||
              Definition.Alignment == Alignment.MiddleCenter ||
              Definition.Alignment == Alignment.MiddleRight
                ? VerticalAlignment.Center
                : VerticalAlignment.Bottom;
    
    private void DoConfigure(TGridColumn column, TEditor editor)
    {
        Configure(column, editor);
        
        // Post-Configure the column - refactor from DynamicGrid.ReloadColumns()
        column.Width = column.Width; // != 0 ? column.Width : double.NaN;

        column.ColumnSizer =
            GridLengthUnitType
                .None; //column.Width != 0 ? GridLengthUnitType.None : GridLengthUnitType.AutoWithLastColumnFill;
        column.HeaderText = string.IsNullOrWhiteSpace(Definition.Caption)
            ? Definition.ColumnName
            : Definition.Caption;

        column.TextAlignment = GetTextAlignment(editor);

        column.HorizontalHeaderContentAlignment = GetHorizontalAlignment(editor);
    }
    private void DoConfigure(TTreeColumn column, TEditor editor)
    {
        Configure(column, editor);
        
        // Post-Configure the column - refactor from DynamicGrid.ReloadColumns()
        column.Width = column.Width; // != 0 ? column.Width : double.NaN;

        column.ColumnSizer = TreeColumnSizer.None;
        column.HeaderText = string.IsNullOrWhiteSpace(Definition.Caption)
            ? Definition.ColumnName
            : Definition.Caption;

        column.TextAlignment = GetTextAlignment(editor);

        column.HorizontalHeaderContentAlignment = GetHorizontalAlignment(editor);
    }
    
    
    protected abstract void Configure(TGridColumn column, TEditor editor);
    protected abstract void Configure(TTreeColumn column, TEditor editor);

    public virtual bool VariableWidth => true;
    public virtual bool VariableHeight => false;

    public virtual bool Filtered => true;

    public virtual bool Editable => true;

}