using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace InABox.Core
{
    public class DFLayoutLookupFieldProperties : DFLayoutFieldProperties<string>
    {
        [DoNotSerialize]
        [NullEditor]
        public List<string> AdditionalPropertiesList = new List<string>();

        [ComboLookupEditor(typeof(PropertyClassLookups))]
        public string LookupType { get; set; } = "";

        // A JSON-serialized Filter for filtering entries in the lookup editor
        [FilterEditor]
        public string Filter { get; set; } = "";

        /// <summary>
        /// A list of comma-separated property names to also pull with the lookup.
        /// </summary>
        //[TextBoxEditor(ToolTip = "A comma-separated list of property names.")]
        [MultiLookupEditor(typeof(AdditionalPropertyLookupGenerator))]
        public string AdditionalProperties
        {
            get => string.Join(',', AdditionalPropertiesList);
            set
            {
                AdditionalPropertiesList = value.Split(',').ToList();
            }
        }

        public override string FormatValue(object? value)
        {
            return value?.ToString() ?? "";
        }

        public override object? ParseValue(object? value)
        {
            return value?.ToString();
        }

        public override IEnumerable<CoreColumn> GetAdditionalColumns()
        {
            if(!CoreUtils.TryGetEntity(LookupType, out var entity))
                return Enumerable.Empty<CoreColumn>();

            return AdditionalPropertiesList.Select(x =>
            {
                if (CoreUtils.TryGetProperty(entity, x, out var property))
                    return new CoreColumn
                    {
                        ColumnName = $"{Code}.{x}",
                        DataType = property.PropertyType
                    };
                return null;
            }).Where(x => x != null).Cast<CoreColumn>();
        }

        protected override void LoadProperties()
        {
            base.LoadProperties();
            LookupType = GetProperty("LookupType", "");
            Filter = GetProperty("Filter", "");
            AdditionalProperties = GetProperty("AdditionalProperties", "");
        }

        protected override void SaveProperties()
        {
            base.SaveProperties();
            SetProperty("LookupType", LookupType);
            SetProperty("Filter", Filter);
            SetProperty("AdditionalProperties", AdditionalProperties);
        }


        private class AdditionalPropertyLookupGenerator : LookupGenerator<object>
        {
            public AdditionalPropertyLookupGenerator(object[] items) : base(items)
            {
            }

            protected override void DoGenerateLookups()
            {
                if (!(Items?.FirstOrDefault() is DFLayoutLookupFieldProperties properties))
                    return;

                if (!CoreUtils.TryGetEntity(properties.LookupType, out var type))
                    return;

                var props = CoreUtils.PropertyList(type, x => x.GetCustomAttribute<DoNotSerialize>() == null, true).Keys.ToList();
                props.Sort();
                foreach (var prop in props)
                {
                    AddValue(prop, prop);
                }
            }
        }
    }
}