using InABox.Configuration;
using InABox.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InABox.Database.Stores;

public class GlobalSettingsStore : Store<GlobalSettings>
{
    private static Dictionary<string, Tuple<Type, Type>> _subStores = new();

    public static void RegisterSubStore<TSettings, TStore>()
        where TSettings : BaseObject, IGlobalConfigurationSettings, new()
        where TStore : ISettingsStoreEventHandler<TSettings>
    {
        _subStores[typeof(TSettings).Name] = new(typeof(TSettings), typeof(TStore));
    }

    private BaseObject GetSettings(GlobalSettings settings, Type TSettings)
    {
        var result = Serialization.Deserialize(TSettings, settings.Contents) as BaseObject;
        if(result is not null)
        {
            result.CommitChanges();
        }
        else
        {
            result = (Activator.CreateInstance(TSettings) as BaseObject)!;
        }
        return result;
    }

    protected override void BeforeSave(GlobalSettings entity)
    {
        base.BeforeSave(entity);
        if(_subStores.TryGetValue(entity.Section, out var subStore))
        {
            (Activator.CreateInstance(subStore.Item2) as ISettingsStoreEventHandler)!.BeforeSave(GetSettings(entity, subStore.Item1));
        }
    }

    protected override void AfterSave(GlobalSettings entity)
    {
        base.AfterSave(entity);
        if(_subStores.TryGetValue(entity.Section, out var subStore))
        {
            (Activator.CreateInstance(subStore.Item2) as ISettingsStoreEventHandler)!.AfterSave(GetSettings(entity, subStore.Item1));
        }
    }

    protected override void BeforeDelete(GlobalSettings entity)
    {
        base.BeforeDelete(entity);
        if(_subStores.TryGetValue(entity.Section, out var subStore))
        {
            (Activator.CreateInstance(subStore.Item2) as ISettingsStoreEventHandler)!.BeforeDelete(GetSettings(entity, subStore.Item1));
        }
    }

    protected override void AfterDelete(GlobalSettings entity)
    {
        base.AfterDelete(entity);
        if(_subStores.TryGetValue(entity.Section, out var subStore))
        {
            (Activator.CreateInstance(subStore.Item2) as ISettingsStoreEventHandler)!.AfterDelete(GetSettings(entity, subStore.Item1));
        }
    }
}

public interface ISettingsStoreEventHandler
{
    void BeforeSave(BaseObject entity);
    void AfterSave(BaseObject entity);
    void BeforeDelete(BaseObject entity);
    void AfterDelete(BaseObject entity);
}
public interface ISettingsStoreEventHandler<T> : ISettingsStoreEventHandler
    where T : BaseObject
{
    void BeforeSave(T entity);
    void AfterSave(T entity);
    void BeforeDelete(T entity);
    void AfterDelete(T entity);

    void ISettingsStoreEventHandler.BeforeSave(BaseObject entity) => BeforeSave((T)entity);
    void ISettingsStoreEventHandler.AfterSave(BaseObject entity) => AfterSave((T)entity);
    void ISettingsStoreEventHandler.BeforeDelete(BaseObject entity) => BeforeDelete((T)entity);
    void ISettingsStoreEventHandler.AfterDelete(BaseObject entity) => AfterDelete((T)entity);
}
