using InABox.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InABox.Wpf.Dashboard;

public class DynamicDashboard
{
    public DynamicDashboardDataComponent DataComponent { get; set; } = new();

    [JsonIgnore]
    public IDynamicDashboardDataPresenter? DataPresenter { get; set; }

    #region Serialization

    private string _presenterProperties = "";

    [JsonProperty(Order = 1, PropertyName = "PresenterProperties")]
    private string PresenterProperties
    {
        get => DataPresenter is not null ? Serialization.Serialize(DataPresenter.Properties) : "";
        set
        {
            _presenterProperties = value;
        }
    }

    [JsonProperty(Order = 2, PropertyName = "PresenterType")]
    private Type? PresenterType
    {
        get => DataPresenter?.GetType();
        set
        {
            if(value is null)
            {
                DataPresenter = null;
            }
            else
            {
                DataPresenter = Activator.CreateInstance(value) as IDynamicDashboardDataPresenter;
                var propertiesType = value.GetInterfaceDefinition(typeof(IDynamicDashboardDataPresenter<>))!.GenericTypeArguments[0];
                DataPresenter!.Properties = Serialization.Deserialize(propertiesType, _presenterProperties)
                    ?? Activator.CreateInstance(propertiesType)!;
            }
        }
    }

    #endregion
}

public static class DynamicDashboardUtils
{
    private static Type[]? _presenterTypes;
    private static bool _loaded;

    [MemberNotNull(nameof(_presenterTypes))]
    private static void LoadTypes()
    {
        if(!_loaded)
        {
            var presenters = new List<Type>();
            var presenterEditors = new Dictionary<Type, Type>();
            foreach(var entity in CoreUtils.Entities)
            {
                if (entity.HasInterface<IDynamicDashboardDataPresenter>())
                {
                    presenters.Add(entity);
                }
            }
            _presenterTypes = presenters.ToArray();
            _loaded = true;
        }
    }

    public static IEnumerable<Type> GetPresenterTypes()
    {
        LoadTypes();
        return _presenterTypes;
    }

    private static JsonSerializerSettings SerializationSettings()
    {
        var settings = Serialization.CreateSerializerSettings();
        settings.TypeNameHandling = TypeNameHandling.Auto;
        return settings;
    }

    public static string Serialize(DynamicDashboard data)
    {
        return JsonConvert.SerializeObject(data, typeof(DynamicDashboard), SerializationSettings());
    }

    public static DynamicDashboard? Deserialize(string? json)
    {
        if (json.IsNullOrWhiteSpace()) return null;
        return JsonConvert.DeserializeObject<DynamicDashboard>(json, SerializationSettings())!;
    }
}
