
using XGame.Framework.Asset.Addressable;
using XGame.Framework.Asset.Addressable.Data;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace XGame.Editor.Asset
{
    public static partial class AddressableHelper
    {
        private static string GetAssetManifestPath(AddressableClassify classify)
        {
            switch (classify)
            {
                case AddressableClassify.BuiltIn:
                    return PathDefine.BuiltInAssetManifestPath;
                case AddressableClassify.Tests:
                    return PathDefine.TestAssetsManifestPath;
                case AddressableClassify.Backup:
                    return PathDefine.AddressableBackupManifestPath;
                default:
                    return PathDefine.ProductAssetManifestPath;
            }
        }

        /// <summary>
        /// 加载 AddressableAssetInfoManifest
        /// </summary>
        /// <returns></returns>
        public static AddressableInfosSo LoadAssetManifest(AddressableClassify classify = AddressableClassify.Product)
        {
            var manifest = AssetDatabase.LoadAssetAtPath<AddressableInfosSo>(GetAssetManifestPath(classify));
            //if (manifest != null)
            //{
            //    manifest.Init();
            //}
            return manifest;
        }
        internal static AddressableInfosSo LoadOrCreateManifest(AddressableClassify classify = AddressableClassify.Product)
        {
            var manifestPath = GetAssetManifestPath(classify);
            var manifest = AssetDatabase.LoadAssetAtPath<AddressableInfosSo>(manifestPath);
            if (manifest == null)
            {
                if ((classify == AddressableClassify.BuiltIn && !Directory.Exists(PathDefine.BuiltInResourcesRelative))
                    || (classify == AddressableClassify.Tests && !Directory.Exists(PathDefine.TestsToAddressable) && !Directory.Exists(PathDefine.BuiltInResTests)))
                {
                    //文件夹不存在
                    return manifest;
                }
                if (!Directory.Exists(PathDefine.ConfigsRelative))
                {
                    Directory.CreateDirectory(PathDefine.ConfigsRelative);
                }
                if (!Directory.Exists(PathDefine.AddressableDataRelative))
                {
                    Directory.CreateDirectory(PathDefine.AddressableDataRelative);
                }
                manifest = ScriptableObject.CreateInstance<AddressableInfosSo>();
                AssetDatabase.CreateAsset(manifest, manifestPath);
            }
            return manifest;
        }
        public static bool TryApplyAddressableName(AddressableInfosSo manifest, string guid,
            string addressableName)
        {
            if (manifest == null)
            {
                return false;
            }
            //待优化
            if (IsValidName(addressableName))
            {
                Debug.LogError($"AddressableName repeat. Please rename it. Name:{addressableName} Path:{AssetDatabase.GUIDToAssetPath(guid)}");
                return false;
            }

            if (manifest.TryApplyAddressableName(guid, addressableName, out var assetInfo))
            {
                var manifestPath = AssetDatabase.GetAssetPath(manifest);
                if (PathDefine.ProductAssetManifestPath.Equals(manifestPath) || PathDefine.BuiltInAssetManifestPath.Equals(manifestPath))
                {
                    ApplyBackupAssetInfo(assetInfo);
                }

                return true;
            }
            return false;
        }
        public static bool TryRemoveAssetByGUID(AddressableInfosSo manifest, string guid)
        {
            if (manifest != null && manifest.TryRemoveAssetByGUID(guid))
            {
                var manifestPath = AssetDatabase.GetAssetPath(manifest);
                if (PathDefine.ProductAssetManifestPath.Equals(manifestPath) || PathDefine.BuiltInAssetManifestPath.Equals(manifestPath))
                { //删除备份
                    var backup = LoadAssetManifest(AddressableClassify.Backup);
                    backup?.TryRemoveAssetByGUID(guid);
                }
                return true;
            }
            return false;
        }

        public static bool RemoveAllInvalidAssets(AddressableInfosSo manifest)
        {
            if (manifest != null && manifest.RemoveAllInvalidAssets())
            {
                var manifestPath = AssetDatabase.GetAssetPath(manifest);
                if (PathDefine.ProductAssetManifestPath.Equals(manifestPath))
                {
                    var backup = LoadAssetManifest(AddressableClassify.Backup);
                    backup?.RemoveAllInvalidAssets();
                }
                return true;
            }
            return false;
        }

        private static void ApplyBackupAssetInfo(AssetInfo assetInfo)
        {
            var backup = LoadAssetManifest(AddressableClassify.Backup);
            if (backup != null)
            {
                var isNameDefault = IsDefaultAddressableName(assetInfo.addressableName, assetInfo.assetGUID);
                if (isNameDefault || !IsValidPath(assetInfo.GetAssetPath()))
                { //默认名字或者无效资源
                    backup.TryRemoveAssetByGUID(assetInfo.assetGUID);
                }
                else
                {
                    var assetInfos = backup.assetInfos.ToList();
                    var index = assetInfos.FindIndex((info => info.assetGUID.Equals(assetInfo.assetGUID)));
                    if (index >= 0)
                    {
                        assetInfos[index] = assetInfo;
                    }
                    else
                    {
                        assetInfos.Add(assetInfo);
                    }
                    backup.SetAssetInfos(assetInfos.ToArray());
                }
            }
        }
        /// <summary>
        /// 收集所有自定义的AddressableName
        /// </summary>
        private static void CollectCustomAddressableNames()
        {
            var backup = LoadAssetManifest(AddressableClassify.Backup);
            if (backup != null)
            {
                var assetInfos = backup.GetAssetInfos();
                assetInfos.Clear();
                AddressableClassify[] operations = { AddressableClassify.BuiltIn, AddressableClassify.Product };
                for (int i = 0; i < operations.Length; i++)
                {
                    var manifest = LoadAssetManifest(operations[i]);
                    if (manifest != null && manifest.assetInfos != null)
                    {
                        foreach (var assetInfo in manifest.assetInfos)
                        {
                            if (IsValidPath(assetInfo.GetAssetPath()) && !IsDefaultAddressableName(assetInfo.addressableName, assetInfo.assetGUID))
                            { //有效资源并且不是默认名字
                                assetInfos.Add(assetInfo);
                            }
                        }
                    }
                }
                backup.SetAssetInfos(assetInfos.ToArray());
            }
        }

        internal static bool IsDefaultAddressableName(string addressableName, string guid, System.Func<string, bool> isContantFileName = null)
        {
            var assetPath = AssetDatabase.GUIDToAssetPath(guid);
            if (string.IsNullOrEmpty(addressableName) || string.IsNullOrEmpty(assetPath))
            {
                return false;
            }
            var fileName = GetFileNameIncludeI18n(assetPath);

            if (addressableName.Equals(fileName))
            {
                return true;
            }
            if (isContantFileName != null && isContantFileName.Invoke(fileName) == false)
            {
                //addressable配置里没有名字为fileName的配置
                return false;
            }
            var ext = Path.GetExtension(assetPath);
            if (addressableName.Equals(($"{fileName}{ext.Replace('.', '_')}").ToLower()))
            {
                return true;
            }

            if (addressableName.Equals(($"{fileName}_{guid.Substring(0, 8)}").ToLower()))
            {
                return true;
            }
            if (addressableName.Equals(($"{fileName}_{guid}").ToLower()))
            {
                return true;
            }
            return false;
        }

    }
}