using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using Excel2Json;
using Fort23.Core;
using Fort23.GameData;

using Utility;
#if !COMBAT_SERVER
using UnityEditor;
using UnityEngine;

#endif

namespace Fort23.UTool
{
    /// <summary>
    /// 配置表组件
    /// </summary>
    public class ConfigComponent : Singleton<ConfigComponent>
    {
     

        private Dictionary<Type, ConfigHolder> _allConfigHolders = new Dictionary<Type, ConfigHolder>();

#if COMBAT_SERVER
        private bool init;
        public void SetConfig(Dictionary<Type, ConfigHolder> allConfigHolders)
        {
            if (init)
            {
                return;
            }

            init = true;
            _allConfigHolders.Clear();
            _allConfigHolders = allConfigHolders;
        }

        public override void Dispose()
        {
            _allConfigHolders.Clear();
            base.Dispose();
        }
#endif
#if !COMBAT_SERVER
#if UNITY_EDITOR
        

    /// <summary>
        /// 预先加载所有配置文件
        /// </summary>
        /// <param name="isLogin">登录的时候只加载指定列表里面的数据，这样可以减少加载时间</param>
        public void EditorPreload(bool isLogin = false)
        {
            _allConfigHolders.Clear();
            ConfigHolder configHolder = null;
            Assembly gameDataAssembly = EventSystem.Instance.GetAssembly("Fort23.GameData.dll");
            if (gameDataAssembly == null)
            {
                LogTool.Error("Fort23.GameData资源加载失败");
                return;
            }

            CTaskAwaitBuffer cTaskAwaitBuffer = new CTaskAwaitBuffer();
            foreach (Type type in gameDataAssembly.GetTypes())
            {
                object[] attrs = type.GetCustomAttributes(typeof(ConfigAttribute), false);
                if (attrs.Length == 0)
                {
                    continue;
                }


                try
                {
                    ConfigAttribute configAttribute =
                        type.GetCustomAttribute(typeof(ConfigAttribute)) as ConfigAttribute;
                    if (configAttribute != null)
                    {
                        TextAsset ta =
                            AssetDatabase.LoadAssetAtPath<TextAsset>(@"Assets\Res\Config\" + configAttribute.prefab);


                        configHolder = JsonHelper.FromJson(ta.text, type) as ConfigHolder;


                        if (configHolder != null)
                        {
                            configHolder.Init();

                            _allConfigHolders[configHolder.ConfigType] = configHolder;
                        }
                        else
                        {
                            LogTool.Error($"JSON转{type.Name}失败!");
                        }
                    }
                    else
                    {
                        LogTool.Error($"配置文件类{type.Name}没有添加ConfigAttribute!");
                    }
                }
                catch (Exception e)
                {
                    LogTool.Error("导表错误" + type);
                    LogTool.Exception(e);
                }
            }

           
            LogTool.Log("所有配置文件初始化完成");
        }
#endif

        /// <summary>
        /// 预先加载所有配置文件
        /// </summary>
        /// <param name="isLogin">登录的时候只加载指定列表里面的数据，这样可以减少加载时间</param>
        public async CTask Preload(bool isLogin = false)
        {
            _allConfigHolders.Clear();
            ConfigHolder configHolder = null;
            Assembly gameDataAssembly = EventSystem.Instance.GetAssembly("Fort23.GameData.dll");
            if (gameDataAssembly == null)
            {
                LogTool.Error("Fort23.GameData资源加载失败");
                return;
            }

            CTaskAwaitBuffer cTaskAwaitBuffer = new CTaskAwaitBuffer();
            foreach (Type type in gameDataAssembly.GetTypes())
            {
                object[] attrs = type.GetCustomAttributes(typeof(ConfigAttribute), false);
                if (attrs.Length == 0)
                {
                    continue;
                }

             

                try
                {
                    ConfigAttribute configAttribute = type.GetCustomAttribute(typeof(ConfigAttribute)) as ConfigAttribute;
                    if (configAttribute != null)
                    {
                       
                        CTask<AssetHandle> cTask = AssetBundleLoadManager.Instance.LoadAssetAsyncTask<TextAsset>(configAttribute.prefab, callBack: delegate(AssetHandle json)
                        {
                            if (json == null)
                            {
                                LogTool.Error("加载配置表错误"+configAttribute.prefab);
                                return;
                            }

                            configHolder = JsonHelper.FromJson(json.AssetObject<TextAsset>().text, type) as ConfigHolder;
                            json.Release();
                            // TODO 验证服预留

                            try
                            {
                                if (configHolder != null)
                                {
                                    configHolder.Init();

                                    _allConfigHolders[configHolder.ConfigType] = configHolder;
                                }
                                else
                                {
                                    LogTool.Error($"JSON转{type.Name}失败!");
                                }
                            }
                            catch (Exception e)
                            {
                                LogTool.Error(e);
                                LogTool.Error($"JSON转{type.Name}失败!");
                            }
                        
#if !COMBAT_SERVER
                        });
                        cTaskAwaitBuffer.AddTask(cTask);
#endif
                    }
                    else
                    {
                        LogTool.Error($"配置文件类{type.Name}没有添加ConfigAttribute!");
                    }
                }
                catch (Exception e)
                {
                    LogTool.Error("导表错误"+type);
                    LogTool.Exception(e);
                }
            }

            await cTaskAwaitBuffer.WaitAll();
            // tasks.Dispose();
            LogTool.Log("所有配置文件初始化完成");
        }
#endif
        public T Get<T>(int ID) where T : struct, IConfig
        {
            
            ConfigHolder configHolder;
            if (!_allConfigHolders.TryGetValue(typeof(T), out configHolder))
            {
                LogTool.Exception(new Exception($"ConfigComponent not found key: {typeof(T).FullName}"));
                return default;
            }

            IConfig iconfig = configHolder.TryGet(ID);
            return iconfig is T ? (T)iconfig : default;
        }



        public T[] GetAll<T>() where T : struct, IConfig
        {
            ConfigHolder configHolder;
            if (!_allConfigHolders.TryGetValue(typeof(T), out configHolder))
            {
                throw new Exception($"ConfigComponent not found key: {typeof(T).FullName}");
            }

            List<IConfig> lists = configHolder.GetAll();
            T[] configs = new T[configHolder.GetAll().Count];
            for (int i = 0; i < configs.Length; i++)
            {
                IConfig iconfig = lists[i];
                configs[i] = iconfig is T ? (T)iconfig : default;
            }

            return configs;
        }
    }
}