using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace InABox.Core
{
    public class CoreGridColumn
    {
        public IProperty Property { get; set; }

        public int Width { get; set; }

        public Alignment Alignment { get; set; }

        public string Format { get; set; }

        public BaseEditor Editor { get; set; }

        public string Caption { get; set; }

        public CoreGridColumn(IProperty property, int width, Alignment alignment, string format, BaseEditor editor, string caption)
        {
            Property = property;
            Width = width;
            Alignment = alignment;
            Format = format;
            Editor = editor;
            Caption = caption;
        }
    }

    /// <summary>
    /// This is the new system for managing default columns on grids. (This replaces <see cref="Visible.Default"/> on <see cref="BaseEditor.Visible"/>).
    /// </summary>
    public static class DefaultColumns
    {
        private static readonly Dictionary<Type, List<CoreGridColumn>> _columns = new Dictionary<Type, List<CoreGridColumn>>();

        public static IEnumerable<CoreGridColumn> GetDefaultColumns(Type T)
        {
            System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(T.TypeHandle);
            if(_columns.TryGetValue(T, out var cols))
            {
                return cols;
            }
            else
            {
                return Enumerable.Empty<CoreGridColumn>();
            }
        }

        public static IEnumerable<CoreGridColumn> GenerateColumns(Type T)
        {
            foreach(var property in DatabaseSchema.RootProperties(T))
            {
                if(property.Editor.Visible != Visible.Hidden && !property.IsParent)
                {
                    yield return CreateColumn(property);
                }
            }
        }

        public static CoreGridColumn GetColumn(Type type, string column)
        {
            var prop = DatabaseSchema.PropertyStrict(type, column);
            var defaults = GetDefaultColumns(type);
            var defaultCol = defaults.FirstOrDefault(x => x.Property == prop);
            if(defaultCol != null)
            {
                return defaultCol;
            }
            return CreateColumn(prop);
        }

        public static CoreGridColumn CreateColumn(IProperty prop)
        {
            var col = new CoreGridColumn(
                prop,
                prop.Editor.Width,
                prop.Editor.Alignment,
                prop.Editor.Format,
                prop.Editor.CloneEditor(),
                prop.Caption);
            return col;
        }

        public static CoreGridColumn CreateColumn<TType, TProperty>(
            Expression<Func<TType, TProperty>> member,
            int? width = null,
            string? caption = null,
            string? format = null,
            Alignment? alignment = null)
        {
            var prop = DatabaseSchema.Property(member) ?? throw new Exception($"Could not find property {CoreUtils.GetFullPropertyName(member, ".")}");
            var col = new CoreGridColumn(
                prop,
                width ?? prop.Editor.Width,
                alignment ?? prop.Editor.Alignment,
                format ?? prop.Editor.Format,
                prop.Editor.CloneEditor(),
                caption ?? prop.Caption);
            return col;
        }

        public static CoreGridColumn Add<TType>(
            Expression<Func<TType, object?>> member,
            int? width = null,
            string? caption = null,
            string? format = null,
            Alignment? alignment = null
        )
        {
            var col = CreateColumn(member, width: width, caption: caption, format: format, alignment: alignment);
            var list = _columns.GetValueOrAdd(typeof(TType));
            list.Add(col);
            return col;
        }
    }
}
