using XGame.Framework.i18n;
using XGame.Framework.Quality;
using System;
using System.Collections.Generic;

namespace XGame.Framework.Asset.Addressable
{
    internal partial class CSharpAddressableManifest : IAddressableManifest, IDisposable
    {
        /// <summary>
        /// Addressable资源集合
        /// </summary>
        private Dictionary<long, Data.AssetInfo> _assetInfoMap;
        /// <summary>
        /// i18n信息集合
        /// <Id, <LangFlag, Id>>
        /// </summary>
        private Dictionary<long, Dictionary<LanguageType, long>> _i18nInfoMap;
        /// <summary>
        /// Lod信息集合
        /// <id, <KQualityLevel, Id>>
        /// </summary>
        private Dictionary<long, Dictionary<XQualityLevel, long>> _lodInfoMap;
        /// <summary>
        /// Resources目录下的资源集合
        /// </summary>
        private HashSet<string> _assetInResources;
        /// <summary>
        /// <addressableId, addressableName>
        /// </summary>
        private Dictionary<long, string> _idToNameMap;
        /// <summary>
        /// <addressableName, addressableId>
        /// </summary>
        private Dictionary<string, long> _nameToIdMap;
        
        public CSharpAddressableManifest()
        {
            _assetInResources = new HashSet<string>();
            _idToNameMap = new Dictionary<long, string>();
            _nameToIdMap = new Dictionary<string, long>();
        }

        public void Init(AddressableInfosSo addressableInfos)
        {
            if (addressableInfos == null)
                return;
            CopyAssetInfos(addressableInfos.assetInfos);
            AddressableUtils.CopyI18nInfos(addressableInfos.i18nInfos, ref _i18nInfoMap);
            AddressableUtils.CopyLodInfos(addressableInfos.lodInfos, ref _lodInfoMap);
        }

        private void CopyAssetInfos(Data.AssetInfo[] assetInfos)
        {
            if (assetInfos == null || assetInfos.Length == 0)
                return;
            if (_assetInfoMap == null)
                _assetInfoMap = new Dictionary<long, Data.AssetInfo>();
            foreach (var assetInfo in assetInfos)
            {
                _assetInfoMap.Add(assetInfo.addressableId, assetInfo);
                SetAssetInfo(assetInfo);
            }
        }
        private void SetAssetInfo(Data.AssetInfo assetInfo)
        {
            _idToNameMap.Add(assetInfo.addressableId, assetInfo.addressableName);
            _nameToIdMap.Add(assetInfo.addressableName, assetInfo.addressableId);
            if (!string.IsNullOrEmpty(assetInfo.relativePath))
            {
                _assetInResources.Add(assetInfo.addressableName);
            }
        }

        #region 接口实现
        public bool ContainsName(string addressableName)
        {
            return _nameToIdMap?.ContainsKey(addressableName) ?? false;
        }

        public bool IsInResourcesByName(string addressableName)
        {
            return _assetInResources?.Contains(addressableName) ?? false;
        }
        public string GetRelativePath(string addressableName)
        {
            if (_nameToIdMap.TryGetValue(addressableName, out var addressableId) &&
                _assetInfoMap.TryGetValue(addressableId, out var assetInfo))
            {
                return assetInfo.relativePath;
            }
            return string.Empty;
        }
        public bool TryGetI18nAddressableName(string addressableName, LanguageType langFlag, out string i18nName)
        {
            i18nName = string.Empty;
            if (langFlag == LanguageType.NONE || _i18nInfoMap == null || string.IsNullOrEmpty(addressableName))
                return false;
            if (_nameToIdMap.TryGetValue(addressableName, out var addressableId) &&
                _i18nInfoMap.TryGetValue(addressableId, out var langMap) &&
                langMap.TryGetValue(langFlag, out var i18nId) &&
                _idToNameMap.TryGetValue(i18nId, out i18nName))
            {
                return true;
            }
            return false;
        }

        public bool TryGetLodAddressableName(string addressableName, XQualityLevel quality, out string lodName)
        {
            lodName = string.Empty;
            if (_lodInfoMap == null || !quality.IsLodQuality() || string.IsNullOrEmpty(addressableName))
            {
                return false;
            }
            if (quality == XQualityLevel.UltraHD)
            {
                //HD使用High的资源
                quality = XQualityLevel.High;
            }
            if (_nameToIdMap.TryGetValue(addressableName, out var addressableId) &&
                _lodInfoMap.TryGetValue(addressableId, out var qualityMap) &&
                qualityMap.TryGetValue(quality, out var lodId) && 
                _idToNameMap.TryGetValue(lodId, out lodName))
            {
                return true;
            }
            return false;
        }
        void IDisposable.Dispose()
        {
            _assetInfoMap?.Clear();
            _assetInfoMap = null;
            _i18nInfoMap?.Clear();
            _i18nInfoMap = null;
            _lodInfoMap?.Clear();
            _lodInfoMap = null;

            _assetInResources?.Clear();
            _assetInResources = null;
            _idToNameMap?.Clear();
            _idToNameMap = null;
            _nameToIdMap?.Clear();
            _nameToIdMap = null;
        }
        #endregion
    }

}
