namespace ChillConnect
{
    using System;
    using System.IO;
    using UnityEngine;
    using System.Linq;
    using System.Text;
    using UnityEngine.Events;
    using System.Collections;
    using System.Collections.Generic;
    using Object = UnityEngine.Object;
    using System.Security.Cryptography;

    public class ChillConnectKit : Singleton<ChillConnectKit>, ILoadAsset
    {
        private const bool IsMD5Encrypt = false;


        private string _assetBundleRootPath = ChillConnectFileKit.GetFilePath();


        private static readonly Dictionary<string, ChillConnectInfo> _cacheAssetBundleInfoDict =
            new Dictionary<string, ChillConnectInfo>();


        private static readonly Dictionary<string, string[]> _cacheDependencyDict = new Dictionary<string, string[]>();

        private static readonly List<ChillConnectInfo> _waitUnloadList = new List<ChillConnectInfo>();

        private static AssetBundleManifest _manifest;

        private static readonly Dictionary<string, string> decryptAssetBundleDict = new Dictionary<string, string>();


        private const int UnloadWaitTime = 30;

        #region 加载AssetBundle的基础方法

        public IEnumerator LoadABFromFileAsync(string assetBundlePath, string bundlePassword,
            UnityAction<AssetBundle> onCompleted)
        {
            yield return LoadDecryptAssetBundle(assetBundlePath, bundlePassword, onCompleted);
        }

        private IEnumerator LoadDecryptAssetBundle(string assetBundlePath, string bundlePassword,
            UnityAction<AssetBundle> onCompleted)
        {
            string decryptPath;
            if (decryptAssetBundleDict.TryGetValue(assetBundlePath, out var outPath) && File.Exists(outPath))
            {
                decryptPath = outPath;
            }
            else
            {
                var cachePath1 = Path.Combine(UnityEngine.Application.persistentDataPath, "Jarvis");
                if (!Directory.Exists(cachePath1))
                {
                    Directory.CreateDirectory(cachePath1);
                }

                var cachePath = Path.Combine(cachePath1, $"decryptedBundle{Guid.NewGuid():N}");


                using (Stream stream1 = File.OpenWrite(cachePath))
                {
                    var decryptedData = AESForFileKit.DecryptToBytes(assetBundlePath, bundlePassword, out var dataSize);
                    yield return stream1.WriteAsync(decryptedData, 0, dataSize);
                }

                decryptPath = cachePath;
                decryptAssetBundleDict.TryAdd(assetBundlePath, decryptPath);
            }

            var request = AssetBundle.LoadFromFileAsync(decryptPath);
            yield return request;
            onCompleted?.Invoke(request.assetBundle);
        }

        private AssetBundle LoadDecryptAssetBundleSync(string assetBundlePath, string bundlePassword)
        {
            string decryptPath;
            if (decryptAssetBundleDict.TryGetValue(assetBundlePath, out var outPath) && File.Exists(outPath))
            {
                decryptPath = outPath;
            }
            else
            {
                var decryptedData = AESForFileKit.DecryptToBytes(assetBundlePath, bundlePassword, out var dataSize);
                var cachePath1 = Path.Combine(UnityEngine.Application.persistentDataPath, "Jarvis");
                if (!Directory.Exists(cachePath1))
                {
                    Directory.CreateDirectory(cachePath1);
                }

                var cachePath = Path.Combine(cachePath1, $"decryptedBundle{Guid.NewGuid():N}");
                while (File.Exists(cachePath))
                {
                    File.Delete(cachePath);
                    cachePath = Path.Combine(cachePath1, $"decryptedBundle{Guid.NewGuid():N}");
                }

                using (Stream stream = File.OpenWrite(cachePath))
                {
                    stream.Write(decryptedData, 0, dataSize);
                    stream.Close();
                }

                decryptPath = cachePath;
                decryptAssetBundleDict.TryAdd(assetBundlePath, decryptPath);
            }

            var assetBundle = AssetBundle.LoadFromFile(decryptPath);
            return assetBundle;
        }

        private IEnumerator LoadAssetFromAssetBundle<T>(AssetBundle assetBundle, string assetName,
            UnityAction<T> onLoadCompleted) where T : Object
        {
            T resultAsset = null;

            if (typeof(T) == typeof(Sprite))
            {
                var texture2D = assetBundle.LoadAsset<Texture2D>(assetName);
                if (texture2D != null)
                {
                    var sprite = Sprite.Create(texture2D,
                        new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));

                    resultAsset = sprite as T;
                }
                else
                {
                    string[] assetNameArray = assetName.Split('.');
                    if (assetNameArray.Length > 1)
                    {
                        var resultAsset1 = assetBundle.LoadAssetWithSubAssets<T>(assetNameArray[0]);
                        resultAsset = Array.Find(resultAsset1, item => item.name == assetNameArray[1]);
                    }
                    else
                    {
                    }
                }
            }
            else
            {
                var assetLoadRequest = assetBundle.LoadAssetAsync<T>(assetName);
                yield return assetLoadRequest;
                var gameObject = assetLoadRequest.asset;
                if (gameObject == null)
                {
                    var subAssetLoadRequest = assetBundle.LoadAssetWithSubAssetsAsync<T>(assetName);
                    yield return subAssetLoadRequest;
                    resultAsset = subAssetLoadRequest.asset as T;
                }
                else
                {
                    resultAsset = gameObject as T;
                }
            }

            onLoadCompleted?.Invoke(resultAsset);
        }

        private void LoadAssetInternal(string assetBundleName, UnityAction<AssetBundle> onCompleted)
        {
            var assetBundlePath = GenerateAssetBundlePath(assetBundleName);

            GetAssetBundle(assetBundlePath, assetBundleName, onCompleted);
        }

        public AssetBundle GetAssetBundle(string assetBundlePath, string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            CrazyAsyKit.StopAction(assetBundleName + "Unload");
            UnWaitUnload(assetBundleName);
            if (IsCacheAssetBundle(assetBundleName))
            {
                CacheDependency(assetBundleName, new[] { assetBundleName });

                var ChillConnectInfo = GetCacheAssetBundle(assetBundleName);
                return ChillConnectInfo?.assetBundle;
            }
            else
            {
                var ChillConnectInfo = new ChillConnectInfo(assetBundleName, null);
                CacheAssetBundle(assetBundleName, ChillConnectInfo);
                var isFileLoadType = File.Exists(assetBundlePath);
                if (isFileLoadType)
                {
                    GetAssetBundleDependency(assetBundleName);
                    var assetBundle =
                        LoadDecryptAssetBundleSync(assetBundlePath, ChillConnectConstant.admsie);
                    ChillConnectInfo.assetBundle = assetBundle;
                    return assetBundle;
                }
            }

            return null;
        }

        public void GetAssetBundle(string assetBundlePath, string assetBundleName, UnityAction<AssetBundle> onCompleted)
        {
            assetBundleName = assetBundleName.ToLower();
            CrazyAsyKit.StopAction(assetBundleName + "Unload");
            UnWaitUnload(assetBundleName);
            if (IsCacheAssetBundle(assetBundleName))
            {
                CacheDependency(assetBundleName, new[] { assetBundleName });

                var ChillConnectInfo = GetCacheAssetBundle(assetBundleName);
                ChillConnectInfo?.callRes(assetBundleName, onCompleted);
            }
            else
            {
                var ChillConnectInfo = new ChillConnectInfo(assetBundleName, onCompleted);
                CacheAssetBundle(assetBundleName, ChillConnectInfo);
                var isFileLoadType = File.Exists(assetBundlePath);
                CrazyAsyKit.StartCoroutine(GetAssetBundleDependency(assetBundleName, delegate
                {
                    if (isFileLoadType)
                    {
                        CrazyAsyKit.StartCoroutine(LoadABFromFileAsync(assetBundlePath,
                            ChillConnectConstant.admsie, bundle =>
                            {
                                if (bundle == null)
                                {
                                    Debug.LogError("加载AssetBundle 失败：" + assetBundleName);
                                    UnCacheAssetBundle(assetBundleName);
                                }
                                else
                                {
                                    ChillConnectInfo abInfo = GetCacheAssetBundle(assetBundleName);
#if UNITY_EDITOR
                                    FileInfo file = new FileInfo(assetBundlePath);

                                    abInfo.SetAssetBundleSize(file.Length);
#endif
                                    abInfo.onLoaded(assetBundleName, bundle);
                                }
                            }));
                    }
                    else
                    {
                        CrazyAsyKit.StartCoroutine(LoadABFromFileAsync(assetBundlePath,
                            ChillConnectConstant.admsie, delegate (AssetBundle bundle)
                            {
                                if (bundle == null)
                                {
                                    Debug.LogError("加载AssetBundle 失败：" + assetBundleName);
                                    UnCacheAssetBundle(assetBundleName);
                                }
                                else
                                {
                                    var abInfoV = GetCacheAssetBundle(assetBundleName);
                                    var file = new FileInfo(assetBundlePath);
                                    abInfoV.SetAssetBundleSize(file.Length);
                                    abInfoV.onLoaded(assetBundleName, bundle);
                                }
                            }));
                    }
                }));
            }
        }

        #region AssetBundle 包的依赖相关

        private IEnumerator GetAssetBundleDependency(string assetBundleName, Action action)
        {
            assetBundleName = assetBundleName.ToLower();

            var allDependencies = new List<string>() { assetBundleName };
            allDependencies.AddRange(GetABDependency(assetBundleName));
            var index = 0;
            CacheDependency(assetBundleName, allDependencies.ToArray());
            var allDepends = allDependencies.Where(dependencyAbName => dependencyAbName != assetBundleName).ToList();

            foreach (var dependencyAbName in allDepends)
            {
                yield return LoadDependencyAssetBundle(assetBundleName, dependencyAbName, delegate { index++; });
            }

            while (index != allDepends.Count)
            {
                yield return new WaitForEndOfFrame();
            }

            action?.Invoke();
        }

        private void GetAssetBundleDependency(string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();

            var allDependencies = new List<string>() { assetBundleName };
            allDependencies.AddRange(GetABDependency(assetBundleName));
            CacheDependency(assetBundleName, allDependencies.ToArray());
            var allDepends = allDependencies.Where(dependencyAbName => dependencyAbName != assetBundleName).ToList();

            foreach (var dependencyAbName in allDepends)
            {
                LoadDependencyAssetBundleSync(assetBundleName, dependencyAbName);
            }
        }

        private IEnumerator LoadDependencyAssetBundle(string parentAssetBundleName, string assetBundleName,
            UnityAction<AssetBundle> onCompleted)
        {
            assetBundleName = assetBundleName.ToLower();
            var assetBundlePath = GenerateAssetBundlePath(assetBundleName, IsMD5Encrypt);

            CrazyAsyKit.StopAction(assetBundleName + "Unload");
            UnWaitUnload(assetBundleName);

            if (IsCacheAssetBundle(assetBundleName))
            {
                CacheAssetBundle(assetBundleName, null, true);
                var ChillConnectInfo = GetCacheAssetBundle(assetBundleName);
                ChillConnectInfo?.callRes(parentAssetBundleName, onCompleted);
            }
            else
            {
                var ChillConnectInfo = new ChillConnectInfo(assetBundleName, onCompleted);
                CacheAssetBundle(assetBundleName, ChillConnectInfo);
                if (File.Exists(assetBundlePath))
                {
                    yield return LoadABFromFileAsync(assetBundlePath, ChillConnectConstant.admsie,
                        delegate (AssetBundle bundle)
                        {
                            if (bundle == null)
                            {
                                Debug.LogError("加载AssetBundle 失败：" + assetBundleName);
                                UnCacheAssetBundle(assetBundleName);
                            }
                            else
                            {
                                GetCacheAssetBundle(assetBundleName).onLoaded(parentAssetBundleName, bundle);
                            }
                        });
                }
                else
                {
                    CrazyAsyKit.StartCoroutine(LoadABFromFileAsync(assetBundlePath,
                        ChillConnectConstant.admsie, delegate (AssetBundle bundle)
                        {
                            if (bundle == null)
                            {
                                Debug.LogError("加载AssetBundle 失败：" + assetBundleName);
                                UnCacheAssetBundle(assetBundleName);
                            }
                            else
                            {
                                GetCacheAssetBundle(assetBundleName).onLoaded(parentAssetBundleName, bundle);
                            }
                        }));
                }
            }
        }

        private AssetBundle LoadDependencyAssetBundleSync(string parentAssetBundleName, string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            var assetBundlePath = GenerateAssetBundlePath(assetBundleName, IsMD5Encrypt);
            CrazyAsyKit.StopAction(assetBundleName + "Unload");
            UnWaitUnload(assetBundleName);

            if (IsCacheAssetBundle(assetBundleName))
            {
                CacheAssetBundle(assetBundleName, null, true);
                var assetBundleInfos = GetCacheAssetBundle(assetBundleName);
                return assetBundleInfos?.assetBundle;
            }

            var ChillConnectInfo = new ChillConnectInfo(assetBundleName, null);
            CacheAssetBundle(assetBundleName, ChillConnectInfo);
            if (File.Exists(assetBundlePath))
            {
                GetAssetBundleDependency(assetBundleName);
                var assetBundle =
                    LoadDecryptAssetBundleSync(assetBundlePath, ChillConnectConstant.admsie);
                ChillConnectInfo.assetBundle = assetBundle;
                return assetBundle;
            }

            return null;
        }


        private string[] GetABDependency(string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            return GetManifest().GetDirectDependencies(assetBundleName);
        }

        #region 依赖关系相关

        private bool IsCacheDependency(string assetBundleName)
        {
            if (_cacheDependencyDict == null || _cacheDependencyDict.Count == 0) return false;
            assetBundleName = assetBundleName.ToLower();
            var isDependency = _cacheDependencyDict.ContainsKey(assetBundleName);

            return isDependency;
        }


        private bool IsOtherDependency(string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            var isDependency = false;
            if (_cacheDependencyDict == null || _cacheDependencyDict.Count == 0) return false;
            foreach (var keyValuePair in _cacheDependencyDict)
            {
                isDependency = keyValuePair.Value.Contains(assetBundleName);
                if (isDependency)
                {
                    break;
                }
            }

            return isDependency;
        }

        private void CacheDependency(string assetBundleName, string[] assetBundleNameArray)
        {
            assetBundleName = assetBundleName.ToLower();
            if (!IsCacheDependency(assetBundleName))
            {
                for (int i = 0; i < assetBundleNameArray.Length; i++)
                {
                    assetBundleNameArray[i] = assetBundleNameArray[i].ToLower();
                }

                _cacheDependencyDict.Add(assetBundleName, assetBundleNameArray);
            }
        }


        private void UnCacheDependency(string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            if (IsCacheDependency(assetBundleName))
            {
                _cacheDependencyDict.Remove(assetBundleName);
            }
        }


        private string[] GetCacheDependency(string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            string[] dependencyList = { };
            if (IsCacheDependency(assetBundleName))
            {
                dependencyList = _cacheDependencyDict[assetBundleName];
            }

            return dependencyList;
        }

        #endregion

        #endregion

        #region 管理已加载的AssetBundle文件

        private void CacheAssetBundle(string assetBundleName, ChillConnectInfo assetBundleInfoV,
            bool isDependency = false)
        {
            assetBundleName = assetBundleName.ToLower();
            if (IsCacheAssetBundle(assetBundleName))
            {
                if (isDependency)
                {
                }
                else
                {
                    return;
                }
            }
            else
            {
                _cacheAssetBundleInfoDict.Add(assetBundleName, assetBundleInfoV);
            }
        }


        private void UnCacheAssetBundle(string assetBundleName)
        {
            if (IsCacheAssetBundle(assetBundleName))
            {
                _cacheAssetBundleInfoDict.Remove(assetBundleName.ToLower());
            }
            else
            {
            }
        }


        private ChillConnectInfo GetCacheAssetBundle(string assetBundleName)
        {
            ChillConnectInfo assetBundle = null;
            if (IsCacheAssetBundle(assetBundleName))
            {
                assetBundle = _cacheAssetBundleInfoDict[assetBundleName.ToLower()];
            }
            else
            {
            }

            return assetBundle;
        }


        private bool IsCacheAssetBundle(string assetBundleName)
        {
            assetBundleName = assetBundleName.ToLower();
            if (_cacheAssetBundleInfoDict == null)
            {
                return false;
            }

            return _cacheAssetBundleInfoDict.ContainsKey(assetBundleName);
        }

        #endregion

        #region 卸载AssetBundle相关

        #region 卸载AssetBundle相关信息管理

        private bool WaitUnload(ChillConnectInfo assetBundleInfoV)
        {
            var isInWait = IsWaitUnload(assetBundleInfoV.assetBundleName);
            if (isInWait) return true;
            assetBundleInfoV.UpdateWaitUnloadCurrentTime();
            _waitUnloadList.Add(assetBundleInfoV);
            return false;
        }


        private bool IsWaitUnloadKey(string assetBundleName)
        {
            var isWaitUnload = false;
            if (_waitUnloadList == null || _waitUnloadList.Count <= 0) return false;
            foreach (var bundleInfo in _waitUnloadList)
            {
                if (bundleInfo == null || !string.IsNullOrEmpty(bundleInfo.assetBundleName)) continue;
                if (!bundleInfo.assetBundleName.Equals(assetBundleName)) continue;
                isWaitUnload = true;
                break;
            }

            return isWaitUnload;
        }


        private bool IsWaitUnload(string assetBundleName)
        {
            var isWaitUnload = false;
            if (_waitUnloadList == null || _waitUnloadList.Count == 0) return false;
            if (!IsWaitUnloadKey(assetBundleName))
            {
                foreach (var waitUnloadAssetBundle in _waitUnloadList)
                {
                    if (waitUnloadAssetBundle == null ||
                        !string.IsNullOrEmpty(waitUnloadAssetBundle.assetBundleName)) continue;
                    isWaitUnload = GetABDependency(waitUnloadAssetBundle.assetBundleName).Contains(assetBundleName);
                    if (isWaitUnload)
                    {
                        break;
                    }
                }
            }
            else
            {
                isWaitUnload = true;
            }

            return isWaitUnload;
        }


        private bool UnWaitUnload(string assetBundleName)
        {
            var isRemove = false;

            foreach (var bundleInfo in _waitUnloadList)
            {
                if (bundleInfo == null) continue;
                if (!bundleInfo.assetBundleName.Equals(assetBundleName)) continue;
                isRemove = _waitUnloadList.Remove(bundleInfo);
                break;
            }

            return isRemove;
        }

        #endregion


        public void UnloadAssetBundle(string assetBundleName,
            bool ignoreDependency = false,
            int unloadWaitTime = 0,
            Action<bool> onCompleted = null)
        {
            if (string.IsNullOrEmpty(assetBundleName))
            {
                onCompleted?.Invoke(false);
                return;
            }

            bool unloadSucceed;
            if (IsCacheAssetBundle(assetBundleName))
            {
                var abInfo = GetCacheAssetBundle(assetBundleName);
                if (abInfo == null)
                {
                    onCompleted?.Invoke(false);
                    return;
                }


                if (WaitUnload(abInfo) && !ignoreDependency)
                {
                    unloadSucceed = false;

                    UnCacheDependency(assetBundleName);

                    onCompleted?.Invoke(unloadSucceed);
                }
                else
                {
                    CrazyAsyKit.StopAction(assetBundleName + "Unload");
                    CrazyAsyKit.StartAction(assetBundleName + "Unload", delegate
                    {
                        unloadSucceed = IsCacheAssetBundle(assetBundleName) &&
                                        UnloadAssetBundleInternal(assetBundleName, ignoreDependency);

                        UnWaitUnload(assetBundleName);

#if UNITY_EDITOR

#endif

                        onCompleted?.Invoke(unloadSucceed);
                    }, unloadWaitTime);
                }
            }
            else
            {
                onCompleted?.Invoke(false);
            }
        }


        private bool UnloadAssetBundleInternal(string assetBundleName, bool isIgnoreDependency = false,
            bool isThorough = false)
        {
            var ChillConnectInfo = GetCacheAssetBundle(assetBundleName);
            if (ChillConnectInfo == null)
            {
                return false;
            }


            var dependencyArray = GetCacheDependency(assetBundleName);


            UnCacheDependency(assetBundleName);


            if (!isIgnoreDependency)
            {
                if (IsOtherDependency(assetBundleName))
                {
                    return false;
                }
            }


            UnCacheAssetBundle(assetBundleName);


            ChillConnectInfo.Unload(isThorough);


            foreach (var dependencyAssetBundleName in dependencyArray)
            {
                if (dependencyAssetBundleName == assetBundleName)
                {
                    continue;
                }


                if (!IsOtherDependency(dependencyAssetBundleName))
                {
                    UnloadAssetBundleInternal(dependencyAssetBundleName, false, isThorough);
                }
                else
                {
                }
            }


            return true;
        }

        #endregion

        #endregion

        #region 封装直接加载资源的方法

        public T GetAsset<T>(string assetBundleName, string assetName) where T : Object
        {
            var assetBundlePath = GenerateAssetBundlePath(assetBundleName);
            var assetBundle = GetAssetBundle(assetBundlePath, assetBundleName);

            return assetBundle.LoadAsset<T>(assetName);
        }


        public void GetAsset<T>(string assetBundleName, string assetName, UnityAction<T> onCompleted) where T : Object
        {
            LoadAssetInternal(assetBundleName, delegate (AssetBundle bundle)
            {
                if (bundle == null)
                {
                    Debug.LogError("加载AssetBundle 失败：" + assetBundleName);
                }
                else
                {
                    CrazyAsyKit.StartCoroutine(LoadAssetFromAssetBundle(bundle, assetName, onCompleted));
                }
            });
        }


        public void InitManifest(string assetBundleManifestName, UnityAction<bool> onCompleted)
        {
            CrazyAsyKit.StopAction(assetBundleManifestName + "Unload");
            if (UnWaitUnload(assetBundleManifestName))
            {
            }
            var assetBundles =
                AssetBundle.LoadFromFile($"{ChillConnectFileKit.GetFilePath()}{ChillConnectConstant.undles}");
            var manifest = assetBundles.LoadAsset<AssetBundleManifest>("assetbundlemanifest");
            _manifest = manifest;
            onCompleted?.Invoke(manifest != null);
        }

        #endregion

        public void RecycleAssetBundle(string assetBundleName, UnityAction onCompleted = null)
        {
            if (IsCacheAssetBundle(assetBundleName))
            {
                var abInfo = GetCacheAssetBundle(assetBundleName);
                abInfo.UnReferenced(assetBundleName);

                RecycleAssetBundleDependency(assetBundleName, UnloadWaitTime);

                if (abInfo.GetReferenced() <= 0)
                {
                    UnloadAssetBundle(assetBundleName, false, UnloadWaitTime);
                }
            }

            onCompleted?.Invoke();
        }

        private void RecycleAssetBundleDependency(string abName, int waitTime)
        {
            var otherAbName = GetCacheDependency(abName);
            if (otherAbName.Length <= 0) return;
            foreach (var dependAbName in otherAbName)
            {
                if (dependAbName == abName) continue;
                var dependAbInfo = GetCacheAssetBundle(dependAbName);
                if (dependAbInfo == null) continue;
                dependAbInfo.UnReferenced(abName);


                if (dependAbInfo.GetReferenced() <= 0)
                {
                    UnloadAssetBundle(dependAbName, false, waitTime);
                }
            }
        }


        #region 其他方法

        private string GenerateAssetBundlePath(string assetBundleName, bool isMD5 = false, bool isManifest = false,
            bool isAddABSuffix = true)
        {
            var fileName = assetBundleName.ToLower();
            if (isMD5)
            {
                fileName = MD5String(fileName) + ".data";
            }

            var filePath = _assetBundleRootPath.Replace("file:///", "") + assetBundleName.ToLower();
            if (isAddABSuffix)
            {
                filePath += ChillConnectConstant.setbun;
            }

            if (!isManifest)
                return filePath;
            if (File.Exists(filePath))
            {
                return filePath;
            }

            return filePath;
        }

        private static string MD5String(string str)
        {
            using var md5 = MD5.Create();
            var hash = md5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes(str));
            var tmp = new StringBuilder();
            foreach (var i in hash)
            {
                tmp.Append(i.ToString("x2"));
            }

            return tmp.ToString();
        }

        #endregion

        public void RecycleAsset(string assetUrl, UnityAction onCompleted)
        {
            RecycleAssetBundle(assetUrl, onCompleted);
        }

        private AssetBundleManifest GetManifest()
        {
            if (_manifest == null)
            {
                Debug.LogError("AssetBundleManifest is null");
                var assetBundles =
                    AssetBundle.LoadFromFile($"{ChillConnectFileKit.GetFilePath()}{ChillConnectConstant.undles}");
                var manifest = assetBundles.LoadAsset<AssetBundleManifest>("assetbundlemanifest");
                _manifest = manifest;
            }

            return _manifest;
        }
    }
}