using System;
using System.Collections.Generic;
using XGame.Framework.Asyncs;

namespace XGame.Framework.Database
{
    public partial class DatabaseModule : IDatabaseModule, IDisposable
    {
        private Dictionary<string, IAsync> _loadingAsyncMap;
        private Dictionary<string, object> _talbeRepoMap;
        public DatabaseModule() 
        {
            _loadingAsyncMap = new Dictionary<string, IAsync>();
            _talbeRepoMap = new Dictionary<string, object>();
        }

        TTable IDatabaseModule.GetByKey<TTable, TRepository>(long key)
        {
            var tableName = typeof(TTable).Name;
            if (_talbeRepoMap.TryGetValue(tableName, out var tableRepo))
            {
                return (tableRepo as TRepository).GetByKey(key);
            }
            return default;
        }

        TTable[] IDatabaseModule.GetAll<TTable, TRepository>()
        {
            var tableName = typeof(TTable).Name;
            if (_talbeRepoMap.TryGetValue(tableName, out var tableRepo))
            {
                return (tableRepo as TRepository).GetAllTables();
            }
            return null;
        }
        IDatabaseAsync<TTable> IDatabaseModule.LoadAsync<TTable, TRepository>(string tableName)
        {
            if (_talbeRepoMap.ContainsKey(tableName))
            {
                Log.Debug($"配置表重复加载. Name:{tableName}");
                return null;
            }
            if (_loadingAsyncMap.TryGetValue(tableName, out var loadingAsync))
            {
                return loadingAsync as IDatabaseAsync<TTable>;
            }
            var dbAsync = new DatabaseAsync<TTable>(tableName);
            _loadingAsyncMap.Add(tableName, dbAsync);
            dbAsync.On((_) =>
            {
                _loadingAsyncMap.Remove(tableName);
                var tableRepo = dbAsync.GetResult<TRepository>();
                if (tableRepo != null)
                {
                    _talbeRepoMap[tableName] = tableRepo;
                }
            });
            dbAsync.Start();
            return dbAsync;
        }

        void IDatabaseModule.Unload(string tableName)
        {
            if (_talbeRepoMap.ContainsKey(tableName))
            {
                _talbeRepoMap.Remove(tableName);
                return;
            }
            if (_loadingAsyncMap.TryGetValue(tableName, out var loadAsync))
            {
                loadAsync.RemoveAll();
                _loadingAsyncMap.Remove(tableName);
            }
        }
        void IDisposable.Dispose()
        {
            foreach(var item in _loadingAsyncMap)
            {
                item.Value.RemoveAll();
            }
            _loadingAsyncMap.Clear();
            foreach(var item in _talbeRepoMap)
            {
                (item.Value as IDisposable)?.Dispose();
            }
            _talbeRepoMap.Clear();
        }
    }
}
