using System;
using System.Collections.Generic;

namespace XGame.Framework.Asset
{
    public class CSharpAssetBundleManifest : IAssetBundleManifest, IDisposable
    {
        /// <summary>
        /// <bundleId, FullName>
        /// </summary>
        private Dictionary<uint, string> _bundleIdToNameMap = new Dictionary<uint, string>();
        /// <summary>
        /// key:bundleFullName
        /// </summary>
        private Dictionary<string, AssetBundleInfo> _bundleInfoMap;
        /// <summary>
        ///  key:bundleFullName
        /// </summary>
        private Dictionary<string, uint> _bundleOffsetMap = new Dictionary<string, uint>();
        /// <summary>
        /// assetName和对应bundleName的缓存
        /// key:assetName
        /// value:bundleName
        /// </summary>
        private Dictionary<string, string> _assetToBundleNameMap = new Dictionary<string, string>();
        /// <summary>
        /// bundle和Dependencies的缓存
        /// 方便查找
        /// </summary>
        private Dictionary<string, string[]> _dependenciesMap = new Dictionary<string, string[]>();


        public CSharpAssetBundleManifest(AssetBundleInfosSo assetBundles)
        {
            _bundleInfoMap = new Dictionary<string, AssetBundleInfo>();
            Init(assetBundles);
        }
        private void Init(AssetBundleInfosSo assetBundles)
        {
            if (assetBundles == null || assetBundles.bundleInfos == null) return;

            foreach (var bundleInfo in assetBundles.bundleInfos)
            {
                var bundleName = bundleInfo.FullName;
                _bundleInfoMap.Add(bundleName, bundleInfo);
                _bundleIdToNameMap.Add(bundleInfo.bundleId, bundleName);
                _bundleOffsetMap.Add(bundleName, bundleInfo.offset);
                if (bundleInfo.assets != null)
                {
                    foreach (var asset in bundleInfo.assets)
                    {
                        if (!_assetToBundleNameMap.ContainsKey(asset))
                        {
                            _assetToBundleNameMap.Add(asset, bundleName);
                        }
                    }
                }
            }
        }

        //public string[] GetAllBundleNames()
        //{
        //    var bundles = BundleInfoMap.Keys.ToArray();
        //    return bundles;
        //}

        //public Hash128 GetAssetBundleHash(string assetBundleName)
        //{
        //    return Hash128.Parse(assetBundleName);
        //}
        public uint GetBundleOffest(string assetBundleName)
        {
            if (_bundleOffsetMap.TryGetValue(assetBundleName, out var offset))
            {
                //Log.Debug($"GetBundleOffest bundle:{assetBundleName} offset:{offset}");
                return offset;
            }
            return 0;
        }


        public string GetBundleNameByAssetName(string assetName)
        {
            if (string.IsNullOrEmpty(assetName))
            {
                return string.Empty;
            }
            if (_assetToBundleNameMap.TryGetValue(assetName, out var bundleName))
            {
                return bundleName;
            }
            return bundleName;
        }

        public string[] GetDependenciesByBundleName(string assetBundleName)
        {
            if (string.IsNullOrEmpty(assetBundleName))
            {
                return null;
            }
            if (_dependenciesMap.TryGetValue(assetBundleName, out string[] dependencies))
            {
                return dependencies;
            }
            if (_bundleInfoMap.TryGetValue(assetBundleName, out var bundleInfo))
            {
                int count = bundleInfo.DependenciesCount;
                if (count > 0)
                {
                    dependencies = new string[count];
                    for (var index = 0; index < count; index++)
                    {
                        var depId = bundleInfo.dependencies[index];
                        dependencies[index] = _bundleIdToNameMap[depId];
                    }
                }
                _dependenciesMap.Add(assetBundleName, dependencies);
            }
            return dependencies;
        }

        //public string[] GetDependenciesByAssetName(string assetName)
        //{
        //    if (string.IsNullOrEmpty(assetName))
        //    {
        //        return null;
        //    }
        //    return GetDependenciesByBundleName(GetBundleNameByAssetName(assetName));
        //}

        void IDisposable.Dispose()
        {
            _dependenciesMap.Clear();
            _assetToBundleNameMap.Clear();
            _bundleInfoMap.Clear();
            _bundleOffsetMap.Clear();
            _bundleIdToNameMap.Clear();
        }
    }
}

