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
{
    /// 
    /// 配置表组件
    /// 
    public class ConfigComponent : Singleton
    {
        private MultiSheetInfoGroup multiSheetInfoGroup;
        private Dictionary _allConfigHolders = new Dictionary();
#if COMBAT_SERVER
        private bool init;
        public void SetConfig(Dictionary 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
        /// 
        /// 预先加载所有配置文件
        /// 
        /// 登录的时候只加载指定列表里面的数据,这样可以减少加载时间
        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(@"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);
                }
            }
            TextAsset multiSheetInfo =
                AssetDatabase.LoadAssetAtPath(@"Assets\Res\Config\multiSheetInfo.json");
            if (multiSheetInfo != null)
            {
                MultiSheetInfoGroup multiSheetInfoGroup =
                    JsonManager.FromJson(multiSheetInfo.text);
                LogTool.Log("加载多表配置" + multiSheetInfoGroup.MultiSheetInfos.Count);
            }
            LogTool.Log("所有配置文件初始化完成");
        }
#endif
        /// 
        /// 预先加载所有配置文件
        /// 
        /// 登录的时候只加载指定列表里面的数据,这样可以减少加载时间
        public async CTask Preload()
        {
            _allConfigHolders.Clear();
            ConfigHolder configHolder = null;
            Assembly gameDataAssembly = EventSystem.Instance.GetAssembly("Fort23.GameData.dll");
            if (gameDataAssembly == null)
            {
                LogTool.Error("Fort23.GameData资源加载失败");
                return;
            }
            AssetHandle multiSheetInfoTask =
                await AssetBundleLoadManager.Instance.LoadAssetAsyncTask("multiSheetInfo.json");
            if (multiSheetInfoTask != null)
            {
                TextAsset textAsset = multiSheetInfoTask.AssetObject();
                multiSheetInfoGroup = JsonManager.FromJson(textAsset.text);
                LogTool.Log("加载多表配置" + multiSheetInfoGroup.MultiSheetInfos.Count);
            }
            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 cTask = AssetBundleLoadManager.Instance.LoadAssetAsyncTask(
                            configAttribute.prefab, callBack: delegate(AssetHandle json)
                            {
                                if (json == null)
                                {
                                    LogTool.Error("加载配置表错误" + configAttribute.prefab);
                                    return;
                                }
                                bool isRoot = false;
                                string[] prefab = configAttribute.prefab.Split("_");
                                string rootName = prefab[0].Split(".")[0];
                                if (prefab.Length > 1)
                                {
                                    MultiSheetInfo multiSheetInfo =
                                        multiSheetInfoGroup.GetMultiSheetInfo(prefab[0]);
                                    if (multiSheetInfo != null)
                                    {
                                        multiSheetInfo.childrenAssetHandle.Add(json);
                                        return;
                                    }
                                }
                                else
                                {
                                    MultiSheetInfo multiSheetInfo =
                                        multiSheetInfoGroup.GetMultiSheetInfo(rootName);
                                    if (multiSheetInfo != null)
                                    {
                                        isRoot = true;
                                    }
                                }
                                configHolder =
                                    JsonHelper.FromJson(json.AssetObject().text, type) as ConfigHolder;
                                json.Release();
                                // TODO 验证服预留
                                try
                                {
                                    if (configHolder != null)
                                    {
                                        configHolder.Init();
                                        _allConfigHolders[configHolder.ConfigType] = configHolder;
                                        if (isRoot)
                                        {
                                            multiSheetInfoGroup.rootType.Add(rootName, 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();
            for (int i = 0; i < multiSheetInfoGroup.MultiSheetInfos.Count; i++)
            {
                MultiSheetInfo multiSheetInfo = multiSheetInfoGroup.MultiSheetInfos[i];
                ConfigHolder rootConfig = multiSheetInfoGroup.rootType[multiSheetInfo.key];
                for (int j = 0; j < multiSheetInfo.childrenAssetHandle.Count; j++)
                {
                    AssetHandle assetHandle = multiSheetInfo.childrenAssetHandle[j];
                    ConfigHolder childConfig =
                        JsonHelper.FromJson(assetHandle.AssetObject().text, rootConfig.GetType()) as
                            ConfigHolder;
                    childConfig.Init();
                    rootConfig.AddChild(childConfig);
                    assetHandle.Release();
                }
                multiSheetInfo.childrenAssetHandle.Clear();
            }
            multiSheetInfoGroup.rootType.Clear();
            multiSheetInfoGroup.MultiSheetInfos.Clear();
            // tasks.Dispose();
            LogTool.Log("所有配置文件初始化完成");
        }
#endif
        public T Get(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() where T : struct, IConfig
        {
            ConfigHolder configHolder;
            if (!_allConfigHolders.TryGetValue(typeof(T), out configHolder))
            {
                throw new Exception($"ConfigComponent not found key: {typeof(T).FullName}");
            }
            List 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;
        }
    }
}