using XGame.Editor.Asset.Addressable;
using XGame.Framework.Asset;
using XGame.Framework.Asset.Addressable;
using XGame.Framework.Asset.Addressable.Data;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace XGame.Editor.Asset
{
    public class AddressableInfosSoEditor
    {
        private readonly AddressableInfosSo manifest;
        /// <summary>
        /// 所有资源
        /// </summary>
        private AddressableAssetFold assetFold;
        /// <summary>
        /// 重名的资源
        /// </summary>
        private AddressableAssetFold nameRepeatFold;
        /// <summary>
        /// 文件名和Addressable不匹配的资源
        /// </summary>
        private AddressableAssetFold nameMismatchFold;
        /// <summary>
        /// 无效的资源
        /// </summary>
        private AddressableAssetFold invalidFold;
        /// <summary>
        /// 等待移除的guid
        /// </summary>
        private readonly List<string> waitingForRemoveGUIDs;

        private AddressableClassify classifyOperation;

        public AddressableInfosSoEditor(AddressableInfosSo manifest)
        {
            this.manifest = manifest;
            waitingForRemoveGUIDs = new List<string>();
            Init();
        }

        void Init()
        {
            InitClassify();
            var allAssetInfos = manifest.GetAssetInfos();
            InitValidAssetInfos(allAssetInfos);
            InitRepeatAssetInfos(allAssetInfos);
            InitNameMismatchAssetInfos(allAssetInfos);
            InitInvalidAssetInfos(allAssetInfos);
        }

        private void InitClassify()
        {
            var assetPath = AssetDatabase.GetAssetPath(manifest);
            if (PathDefine.ProductAssetManifestPath.Equals(assetPath))
            {
                classifyOperation = AddressableClassify.Product;
            }
            else if (PathDefine.BuiltInAssetManifestPath.Equals(assetPath))
            {
                classifyOperation = AddressableClassify.BuiltIn;
            }
            else if (PathDefine.AddressableBackupManifestPath.Equals(assetPath))
            {
                classifyOperation = AddressableClassify.Backup;
            }
            else
            {
                classifyOperation = AddressableClassify.Tests;
            }
            Debug.Log($"InitClassify :{classifyOperation}  assetPath:{assetPath}");
        }

        private void InitValidAssetInfos(List<AssetInfo> allAssetInfos)
        {
            if (assetFold != null)
            {
                assetFold.Clear();
            }
            else
            {
                assetFold = new AddressableAssetFold("Assets")
                {
                    IsFoldout = false
                };
            }

            assetFold.IsFoldout = false;
            assetFold.AddChildrenEvent += delegate()
            {
                int count = 0;
                var validAssetInfos = allAssetInfos.FindAll((info => {
                    EditorUtility.DisplayProgressBar("收集资源中...", info.GetAssetPath(), (++count) / (float)allAssetInfos.Count);
                    return AddressableHelper.IsValidPath(info.GetAssetPath());
                }));
                EditorUtility.ClearProgressBar();
                foreach (var assetInfo in validAssetInfos)
                {
                    assetFold.AddFileWithFold(assetInfo, OnApplyFile);
                }
            };
        }
        private void InitRepeatAssetInfos(List<AssetInfo> allAssetInfos)
        {
            if (nameRepeatFold != null)
            {
                nameRepeatFold.Clear();
            }
            else
            {
                nameRepeatFold = new AddressableAssetFold("重名资源");
            }
            nameRepeatFold.IsFoldout = false;
            nameRepeatFold.AddChildrenEvent += delegate ()
            {
                //列出所有重名的资源
                //var validAssetInfos = allAssetInfos.FindAll((info => AddressableHelper.IsValidPath(info.GetAssetPath())));
                Dictionary<string, List<AssetInfo>> fileNameMap = new Dictionary<string, List<AssetInfo>>();
                for (int i = 0; i < allAssetInfos.Count; i++)
                {
                    var assetInfo = allAssetInfos[i];
                    var assetPath = assetInfo.GetAssetPath();

                    EditorUtility.DisplayProgressBar("收集重名资源中...", assetPath, i / (float)allAssetInfos.Count);
                    if (!AddressableHelper.IsValidPath(assetPath))
                    {
                        //过滤无效资源
                        continue;
                    }
                    var fileName = AddressableHelper.GetFileNameIncludeI18n(assetPath);

                    // ReSharper disable once AssignNullToNotNullAttribute
                    if (!fileNameMap.TryGetValue(fileName, out var lstAssetInfos))
                    {
                        lstAssetInfos = new List<AssetInfo>();
                        fileNameMap.Add(fileName, lstAssetInfos);
                    }
                    lstAssetInfos.Add(assetInfo);
                }
                EditorUtility.ClearProgressBar();

                foreach (var item in fileNameMap)
                {
                    if (item.Value.Count <= 1)
                        continue;
                    var fold = new AddressableAssetFold(item.Key);
                    nameRepeatFold.AddChild(fold);
                    foreach (var assetInfo in item.Value)
                    {
                        fold.AddFile(assetInfo, OnApplyFile, FileSign.None);
                    }
                }
            };
           
        }
        private void InitNameMismatchAssetInfos(List<AssetInfo> allAssetInfos)
        {
            if (nameMismatchFold != null)
            {
                nameMismatchFold.Clear();
            }
            else
            {
                nameMismatchFold = new AddressableAssetFold("文件名不匹配资源")
                {
                    IsFoldout = false
                };
            }

            nameMismatchFold.IsFoldout = false;
            nameMismatchFold.AddChildrenEvent += delegate ()
            {
                var addressableNames = new HashSet<string>();
                foreach (var assetInfo in allAssetInfos)
                {
                    addressableNames.Add(assetInfo.addressableName);
                }
                var count = 0;
                var mismatchAssetInfos = allAssetInfos.FindAll((info => {
                    EditorUtility.DisplayProgressBar("收集资源中...", info.GetAssetPath(), (++count) / (float)allAssetInfos.Count);
                    return AddressableHelper.IsValidPath(info.GetAssetPath()) && !AddressableHelper.IsDefaultAddressableName(info.addressableName, info.assetGUID, (fileName)=> addressableNames.Contains(fileName)); 
                }));
                EditorUtility.ClearProgressBar();
                foreach (var assetInfo in mismatchAssetInfos)
                {
                    nameMismatchFold.AddFile(assetInfo, OnApplyFile, FileSign.NameMismatch);
                }
            };
        }
        private void InitInvalidAssetInfos(List<AssetInfo> allAssetInfos)
        {
            if (invalidFold != null)
            {
                invalidFold.Clear();
            }
            else
            {
                invalidFold = new AddressableAssetFold("无效资源")
                {
                    IsFoldout = true
                };
            }
            var invalidAssetInfos = allAssetInfos.FindAll((info => !AddressableHelper.IsValidPath(info.GetAssetPath())));
            //invalidAssetInfos.Sort();
            foreach (var assetInfo in invalidAssetInfos)
            {
                invalidFold.AddInvalidFile(assetInfo, OnRemoveFile);
            }
        }

        private bool OnApplyFile(ApplyEvnetContext context)
        {
            if (classifyOperation == AddressableClassify.BuiltIn)
            {
                Alert("内置资源禁止修改AddressableName.");
                return false;
            }
            if (classifyOperation == AddressableClassify.Backup)
            {
                Alert("禁止修改备份文件.");
                return false;
            }
            var result = AddressableHelper.TryApplyAddressableName(manifest, context.assetGUID, context.addressableName);
            if (result && context.fileSign == FileSign.NameMismatch && AddressableHelper.IsDefaultAddressableName(context.addressableName, context.assetGUID))
            {
                // 是名字不匹配的资源，且修改为默认名字，则删除
                nameMismatchFold.RemoveChild(context.assetEntry);
            }
            return result;
        }
        private void Alert(string content)
        {
            EditorWindow.focusedWindow.ShowNotification(new GUIContent(content));
        }
        private void OnRemoveFile(string guid)
        {
            // 不直接移除，等到invalidFold的GUI迭代结束再统一移除
            if (!waitingForRemoveGUIDs.Contains(guid))
            {
                waitingForRemoveGUIDs.Add(guid);
            }
        }

        public void OnGUI()
        {
            DrawValidAssetInfos();
            DrawRepeatAssetInfos();
            DrawNameMismatchAssetInfos();
            DrawInvalidAssetInfos();
            DrawMsg();
        }

        private void DrawValidAssetInfos()
        {
            if (assetFold == null)
                return;
            //开始垂直排序
            EditorGUILayout.BeginVertical("Box");
            assetFold.GUI();
            EditorGUILayout.EndVertical();

        }
        private void DrawRepeatAssetInfos()
        {
            if (nameRepeatFold == null)
                return;
            //开始垂直排序
            EditorGUILayout.BeginVertical("Box");
            nameRepeatFold.GUI();
            EditorGUILayout.EndVertical();
        }
        private void DrawNameMismatchAssetInfos()
        {
            if (nameMismatchFold == null)
                return;
            //开始垂直排序
            EditorGUILayout.BeginVertical("Box");
            nameMismatchFold.GUI();
            EditorGUILayout.EndVertical();
        }
        private void DrawInvalidAssetInfos()
        {
            if (invalidFold == null)
                return;
            //开始垂直排序
            EditorGUILayout.BeginVertical("Box");
            //绘制文件夹内容
            invalidFold.GUI();
            //移除指定的无效资源
            if (manifest != null && waitingForRemoveGUIDs.Count > 0)
            {
                var success = false;
                foreach (var guid in waitingForRemoveGUIDs)
                {
                    if (AddressableHelper.TryRemoveAssetByGUID(manifest, guid))
                    {
                        success = true;
                    }
                }
                waitingForRemoveGUIDs.Clear();
                if (success)
                {
                    InitInvalidAssetInfos(manifest.GetAssetInfos());
                }
            }
            //移除所有无效资源
            if (invalidFold.ChildCount > 0)
            {
                if (GUILayout.Button("移除所有无效资源", GUILayout.Width(120)))
                {
                    if (AddressableHelper.RemoveAllInvalidAssets(manifest))
                    {
                        InitInvalidAssetInfos(manifest.GetAssetInfos());
                    }
                }
            }
            EditorGUILayout.EndVertical();
        }
        private void DrawMsg()
        {
            GUILayout.Space(20);
            if (classifyOperation == AddressableClassify.Tests)
            {
                EditorGUILayout.HelpBox("友情提示： 该文件为本地测试资源配置文件，禁止上传，否则后果自负。", MessageType.Error);
            }
            else
            {
                EditorGUILayout.HelpBox("友情提示：如有修改请及时上传同步 Manifest 文件，否则后果自负。", MessageType.Warning);
            }
            //GUI.color = Color.red;
            //GUILayout.TextArea("友情提示：如有修改请及时上传同步 Manifest 文件，否则后果自负。", GUI.skin.textArea);
            //GUI.color = Color.white;

            GUILayout.Space(5);
            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.ObjectField("Manifest", manifest, typeof(Object), false);
            EditorGUI.EndDisabledGroup();
        }

        public void Close()
        {
            assetFold?.Clear();
            nameRepeatFold?.Clear();
            invalidFold?.Clear();
            waitingForRemoveGUIDs.Clear();
        }


    }



}

