using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using InABox.Core;

namespace InABox.DynamicGrid;

public class ColumnNameGenerator : LookupGenerator<object>
{
    public ColumnNameGenerator(object[] items) : base(items)
    {
        //DynamicGridColumns cols = new DynamicGridColumns();
        //cols.ExtractColumns(type, "");
        //foreach (DynamicGridColumn col in cols.Where(x => (x.Editor != null) && (x.Editor.Visible != Visible.Disabled)))
        //    AddValue(col.ColumnName, col.ColumnName);
    }
}

public class DynamicColumnNameEditor : BaseEditor
{
    public IDynamicGridColumnSchema? Schema { get; set; }

    protected override BaseEditor DoClone()
    {
        return new DynamicColumnNameEditor()
        {
            Schema = Schema
        };
    }
}

public class DynamicGridColumn : DynamicColumnBase
{
    public DynamicGridColumn()
    {
        Editor = new NullEditor();
    }
    public DynamicGridColumn(IProperty property)
    {
        ColumnName = property.Name;
        Width = property.Editor.Width;
        Alignment = property.Editor.Alignment;
        Format = property.Editor.Format;
        Editor = property.Editor.CloneEditor();
        Caption = property.Caption;
    }
    public DynamicGridColumn(DynamicGridColumn column)
    {
        ColumnName = column.ColumnName;
        Width = column.Width;
        Caption = column.Caption;
        Format = column.Format;
        Alignment = column.Alignment;
        Editor = column.Editor.CloneEditor();
    }
    public DynamicGridColumn(CoreGridColumn column)
    {
        ColumnName = column.Property.Name;
        Width = column.Width;
        Caption = column.Caption;
        Format = column.Format;
        Alignment = column.Alignment;
        Editor = column.Editor.CloneEditor();
    }
    public DynamicGridColumn(string column, Type dataType, BaseEditor? editor = null)
    {
        editor ??= EditorUtils.GetEditor(dataType) ?? new NullEditor();

        ColumnName = column;
        
        Width = editor.Width;
        Caption = editor.Caption;
        Format = editor.Format;
        Alignment = editor.Alignment;
        Editor = editor.CloneEditor();
    }

    [DynamicColumnNameEditor(Visible = Visible.Default)]
    [EditorSequence(1)]
    public string ColumnName { get; set; }

    [EditorSequence(2)]
    [IntegerEditor(Visible = Visible.Default)]
    public int Width { get; set; }

    [EditorSequence(3)]
    [TextBoxEditor(Visible = Visible.Default)]
    public string Caption { get; set; }

    [EditorSequence(4)]
    [TextBoxEditor(Width = 60, Visible = Visible.Default)]
    public string Format { get; set; }

    [EnumLookupEditor(typeof(Alignment), Width = 100, Visible = Visible.Default)]
    [EditorSequence(5)]
    public Alignment Alignment { get; set; }

    public BaseEditor Editor { get; set; }

    public VerticalAlignment VerticalAlignment() => Alignment.VerticalAlignment();

    public HorizontalAlignment HorizontalAlignment(Type datatype) => Alignment.HorizontalAlignment(datatype);

    public override string ToString()
    {
        return ColumnName;
    }

    public DynamicGridColumn Copy()
    {
        return new(this);
    }

    public static DynamicGridColumn FromProperty(IProperty property)
    {
        return new DynamicGridColumn(property);
    }

    public static DynamicGridColumn FromCoreGridColumn(CoreGridColumn column)
    {
        return new DynamicGridColumn(column);
    }

    public static DynamicGridColumn? FromCoreColumn(CoreColumn column)
    {
        var editor = EditorUtils.GetEditor(column.DataType);
        if (editor is null) return null;

        return new DynamicGridColumn
        {
            ColumnName = column.ColumnName,
            Width = editor.Width,
            Caption = editor.Caption,
            Format = editor.Format,
            Alignment = editor.Alignment,
            Editor = editor.CloneEditor()
        };
    }
}

#region Column Schema

public interface IDynamicGridColumnSchema
{
    IEnumerable<string> ColumnNames { get; }

    DynamicGridColumn GetColumn(string column);

    string? GetComment(string column);

    bool IsVisible(string column);
}
public class DynamicGridObjectColumnSchema(Type t, IEnumerable<string>? columnNames = null) : IDynamicGridColumnSchema
{
    public event GetAvailableColumnsEvent? OnProcessColumns;

    public bool DirectEdit { get; set; }

    private string[]? _columnNames = columnNames?.ToArray();

    public IEnumerable<string> ColumnNames => _columnNames ?? ProcessColumns().Select(x => x.ColumnName);

    private IEnumerable<DynamicGridColumn> ProcessColumns()
    {
        var result = new List<DynamicGridColumn>();
        var cols = new DynamicGridColumns();
        cols.ExtractColumns(t);
        foreach (var col in cols)
        {
            if (col.Editor == null)
                continue;
            if (col.Editor is NullEditor)
                continue;
            if (col.Editor.Visible != Visible.Hidden)
            {
                result.Add(col);
                continue;
            }

            if (!DirectEdit)
                continue;

            if (col.Editor.Editable.IsEditable() && col.ColumnName.Split('.').Length <= 2)
                result.Add(col);
        }
        result.Sort((a, b) => a.ColumnName.CompareTo(b.ColumnName));

        var args = new GetAvailableColumnsEventArgs(result);
        OnProcessColumns?.Invoke(args);

        return args.Columns;
    }

    public DynamicGridColumn GetColumn(string column)
    {
        return DynamicGridColumn.FromCoreGridColumn(DefaultColumns.GetColumn(t, column));
    }

    public string? GetComment(string column)
    {
        return DatabaseSchema.Property(t, column)?.Comment;
    }

    public bool IsVisible(string column)
    {
        return (DatabaseSchema.Property(t, column)?.Editor.Visible ?? Visible.Optional) != Visible.Hidden;
    }
}

#endregion
