using XGame.Framework;
using XGame.Framework.Asyncs;
using XGame.Framework.i18n;
using XGame.Framework.Quality;

#if UNITY_EDITOR
using System.Linq;
#endif

namespace XGame.Framework.Asset
{
    public sealed partial class AssetManager
    {
        private static IAssetManager _assetMgr;
        private static IAssetManager Instance => _assetMgr ?? (_assetMgr = new AssetManager());

        public static void ChangedLanguage(LanguageType langFlag)
        {
            if (_assetMgr != null && _assetMgr is AssetManager manager)
            {
                manager.SetLangueType(langFlag);
            }
            else
            {
                AssetsLog.Error($"IAssetManager has dispose. But ChangedLanguage Event callback.");
            }
        }

        public static void ChangeQualityLevel(XQualityLevel quality)
        {
            if (_assetMgr != null && _assetMgr is AssetManager manager)
            {
                manager.SetQuality(quality);
            }
            else
            {
                AssetsLog.Error($"IAssetManager had dispose. But ChangeQualityLevel Event callback.");
            }

        }
        /// <summary>
        /// 转换AddressableName
        /// 会根据游戏当前语言、品质等级返回对应的AddressableName
        /// </summary>
        /// <param name="addressableName"></param>
        /// <returns></returns>
        public static string ConvertAddressableName(string addressableName)
        {
            if (_assetMgr != null)
            {
                return _assetMgr.ConvertAddressableName(addressableName);
            }
            return addressableName;
        }
        /// <summary>
        /// 同步加载接口
        /// 非必要不要使用
        /// 使用该接口加载的资源严禁使用Object.Destroy销毁，只能使用Recycle(obj)方法回收
        /// </summary>
        /// <typeparam name="TResult">返回值类型</typeparam>
        /// <param name="addressableName">可寻址资源名字</param>
        /// <returns>返回泛型对象</returns>
        public static TResult LoadSync<TResult>(string addressableName)
        {
#if UNITY_EDITOR
            if (TryLoadSyncForEditor(addressableName, out TResult result))
            {
                return result;
            }
#endif 
            return Instance.LoadSync<TResult>(addressableName);
        }

        /// <summary>
        /// 异步加载接口
        /// 使用该接口加载的资源严禁使用Object.Destroy销毁，只能使用Recycle(obj)方法回收
        /// </summary>
        /// <typeparam name="TResult">返回对象类型</typeparam>
        /// <param name="addressableName">可寻址资源名字</param>
        /// <returns>返回异步回调</returns>
        public static IAssetLoadAsync<TResult> LoadAsync<TResult>(string addressableName)
        {
#if UNITY_EDITOR
            Assert.IsTrue(UnityEngine.Application.isPlaying, "非运行时加载资源请使用 AddressableHelper.LoadAssetByAddressableName()");
#endif 
            return Instance.LoadAsync<TResult>(addressableName);
        }

        /// <summary>
        /// 加载Scene的AssetBundle到内存
        /// </summary>
        /// <param name="bundleName"></param>
        public static IAsync LoadSceneBundle(string sceneName)
        {
            return Instance.LoadSceneBundle(sceneName);
        }

        public static void UnLoadSceneBundle(string sceneName)
        {
            Instance.UnLoadSceneBundle(sceneName);
        }

        /// <summary>
        /// 回收资源
        /// </summary>
        /// <param name="obj"></param>
        public static void Recycle(object obj)
        {
#if UNITY_EDITOR
            if (!UnityEngine.Application.isPlaying)
            {
                return;
            }
#endif
            Instance.Recycle(obj);
        }

        /// <summary>
        /// 停止指定的异步加载
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="async"></param>
        public static void StopAsync<TResult>(IAssetLoadAsync<TResult> async)
        {
            Instance.StopAsync(async);
        }

        /// <summary>
        /// 卸载当前未使用的资源
        /// </summary>
        public static void UnloadUnusedAssets()
        {
            Instance.UnloadUnusedAssets();
        }
        public static IAsync Dispose()
        {
            if (_assetMgr != null)
            {
                var async = _assetMgr.Dispose();
                async.On((aAsync => { _assetMgr = null; }));
                return async;
            }
            return null;
        }
        /// <summary>
        /// 设置资源的预加载标记
        /// </summary>
        /// <param name="addressableName"></param>
        /// <param name="isPreload"></param>
        public static void SetPreloadTag(string addressableName, bool isPreload)
        {
             if (_assetMgr is IAssetCacheHandle handle)
            {
                handle.SetPreloadTag(addressableName, isPreload);
            }
        }


#if UNITY_EDITOR
        private static IAssetLoadHandler _loadHandler;
        private static IAssetLoadHandler LoaderHandler
        {
            get
            {
                if (_loadHandler == null)
                {
                    var hostEditorName = "Framework.Editor";
                    var adapterType = typeof(IAssetLoadHandler);
                    var handlerImplType = System.AppDomain.CurrentDomain.GetAssemblies()
                        .First(assembly => assembly.GetName().Name.Equals(hostEditorName))
                        .GetTypes().First(type => adapterType.IsAssignableFrom(type));
                    if (handlerImplType != null)
                    {
                        _loadHandler = System.Activator.CreateInstance(handlerImplType) as IAssetLoadHandler;
                    }
                    else
                    {
                        UnityEngine.Debug.LogError("没有找到 IAssetLoaderHandler 的实现类。");
                    }
                }
                return _loadHandler;
            }
        }
        private static bool TryLoadSyncForEditor<TResult>(string addressableName, out TResult result)
        {
            if (UnityEngine.Application.isPlaying == false)
            {
                if (LoaderHandler != null)
                {
                    result = LoaderHandler.LoadSync<TResult>(addressableName);
                }
                else
                {
                    result = default(TResult);
                }
                return true;
            }
            result = default;
            return false;
        }
#endif
    }
}

