using System;
using System.Collections.Generic;
using System.IO;
using HybridCLR.Editor;
using HybridCLR.Editor.Commands;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using YooAsset.Editor;

namespace Stary.Evo.Editor
{
    public class MarkAdressable : MonoBehaviour
    {
        private static AssetBundleCollectorPackage package;
        private static string packageName;

        private static string[] configNames = new[] { "DomainConfig" };


        public static string DomainRoot
        {
            get { return Application.dataPath + "/Domain"; }
        }
        // public static string AtlasRemotedRoot
        // {
        //     get { return Application.dataPath + "/AddressableRes/Sprites"; }
        // }
        //
        // public static string SpriteRemotedAtlas
        // {
        //     get { return Application.dataPath + "/AddressableRes/SpriteAtlas"; }
        // }


        //[MenuItem("Evo/Hotfix/BuildAll")]
        public static void BuildAll()
        {
            PrebuildCommand.GenerateAll();
            Debug.Log("UnityEvo:Build【GenerateAll】完成");
            AddHotfixAddressableDll();
            Debug.Log("UnityEvo:Build【CopyHotfixAddressableDll】完成");
            AddMark();
            Debug.Log("UnityEvo:Build【MarkAsset】完成");
        }


        //[MenuItem("Evo/Hotfix/Addressable")]
        public static void AddHotfixAddressableDll()
        {
            CopyDllHotUpdateAssembly(BuildAssetWindow.GetBuildPackageName(), $"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/AddressableRes");
            CopyDllStrippedAOTDllOutputRootDir($"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/AddressableRes");


            //EditorUtility.DisplayDialog("自动标记", "自动Hotfix成功", "确定");
        }

        private static void CopyDllHotUpdateAssembly(string domain, string target)
        {
            //读取打包dll位置
            string hotUpdateDir =
                $"{SettingsUtil.HybridCLRSettings.hotUpdateDllCompileOutputRootDir}/{EditorUserBuildSettings.activeBuildTarget}";
            foreach (var dll in SettingsUtil.HybridCLRSettings.hotUpdateAssemblyDefinitions)
            {
                if (dll.name.Contains(domain)) 
                {
                    string hotfixDllPath = $"{hotUpdateDir}/{dll.name}.dll";
                    string hotfixDllPathTarget =
                        $"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll.name}.dll.bytes";
                    string hotfixDllPathPdb = $"{hotUpdateDir}/{dll.name}.pdb";
                    string hotfixDllPathPdbTarget =
                        $"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll.name}.pdb.bytes";
                    FileUtility.Copy(hotfixDllPath, hotfixDllPathTarget, true);
                    FileUtility.Copy(hotfixDllPathPdb, hotfixDllPathPdbTarget, true);
                }
            }

            foreach (var dll in SettingsUtil.HybridCLRSettings.hotUpdateAssemblies)
            {
                if (dll.Contains(domain))
                {
                    string hotfixDllPath = $"{hotUpdateDir}/{dll}.dll";
                    string hotfixDllPathTarget =
                        $"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll}.dll.bytes";
                    string hotfixDllPathPdb = $"{hotUpdateDir}/{dll}.pdb";
                    string hotfixDllPathPdbTarget =
                        $"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll}.pdb.bytes";
                    FileUtility.Copy(hotfixDllPath, hotfixDllPathTarget, true);
                    FileUtility.Copy(hotfixDllPathPdb, hotfixDllPathPdbTarget, true);
                }
            }
        }

        private static void CopyDllStrippedAOTDllOutputRootDir(string target)
        {
            //读取打包dll位置
            string hotUpdateDir =
                $"{SettingsUtil.HybridCLRSettings.strippedAOTDllOutputRootDir}/{EditorUserBuildSettings.activeBuildTarget}";
            foreach (var dll in SettingsUtil.HybridCLRSettings.patchAOTAssemblies)
            {
                string hotfixDllPath = $"{hotUpdateDir}/{dll}";
                string hotfixDllPathTarget =
                    $"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll}.bytes";
                FileUtility.Copy(hotfixDllPath, hotfixDllPathTarget, true);
            }
        }

        //[MenuItem("Evo/Hotfix/标记资源")]
        public static void AddMark()
        {
            //copydll
            AddHotfixAddressableDll();
            //清空旧数据
            YooAsset.Editor.AssetBundleCollectorSettingData.ClearAll();


            packageName = "";
            package = null;
            string configPath =
                $"Assets/Domain/{BuildAssetWindow.GetBuildPackageName()}/Conf/HotfixMainResDomain.asset";
            HotfixMainResDomain hotfixMainResDomain = AssetDatabase.LoadAssetAtPath<HotfixMainResDomain>(configPath);
            packageName = hotfixMainResDomain.hotfixMainResDomainEntity.domain;
            Mark();
            CreateRes(packageName,
                $"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/AddressableRes",
                $"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/HotUpdate");

            EditorUtility.DisplayDialog("自动标记", "自动标记成功", "确定");
        }


        // [MenuItem("Evo/Hotfix/一键Res")]
        public static void CreateRes(string domain, string resPath, string outputPath)
        {
            FileGet.CreateClass("Res", domain, outputPath,
                (a) => { FileGet.CreateContent(a, resPath, "\t"); });
        }

        #region 自动标记

        public static Dictionary<string, string> addressDic = new Dictionary<string, string>();

        public static Dictionary<string, AssetBundleCollectorGroup> collectorGroupDic =
            new Dictionary<string, AssetBundleCollectorGroup>();

        public static void Mark()
        {
            addressDic.Clear();
            collectorGroupDic.Clear();

            ///创建分组
            string remotedRoot = $"{DomainRoot}/{packageName}/AddressableRes";
            DirectoryInfo[] dirs = new DirectoryInfo(remotedRoot).GetDirectories();

            var setting = YooAsset.Editor.AssetBundleCollectorSettingData.Setting;
            setting.ShowPackageView = true;
            setting.UniqueBundleName = true;
            //创建Package文件
            package = YooAsset.Editor.AssetBundleCollectorSettingData.CreatePackage(packageName);

            //检测Packages是否存在TestPackage
            package.PackageName = packageName;
            package.EnableAddressable = true;
            package.IncludeAssetGUID = true;
            package.AutoCollectShaders = true;
            package.IgnoreRuleName = "NormalIgnoreRule";


            //检测Packages是否存在Group
            foreach (var info in dirs)
            {
                string groupName = info.Name;

                if (info.Name != "Atlas")
                {
                    AssetBundleCollectorGroup collectorGroup =
                        YooAsset.Editor.AssetBundleCollectorSettingData.CreateGroup(package, groupName);
                    collectorGroup.AssetTags = groupName;
                    if (!collectorGroupDic.ContainsKey(groupName))
                    {
                        collectorGroupDic.Add(groupName, collectorGroup);
                    }
                    else
                    {
                        Debug.LogError("分组 ： " + groupName + "已存在，请检查资源目录，避免重复");
                    }
                }

                AutoMarkRootAddress(info);
                // if (info.Name != "SpriteAtlas" && info.Name != "Atlas")
                //     AutoMark(info.Name);
            }


            ///自动创建图集
            Debug.Log("开始创建图集");
            AutoCreateSpriteAtlas(remotedRoot);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            MarkStatus();
            YooAsset.Editor.AssetBundleCollectorSettingData.FixFile();

            // CreateRes();
            Debug.Log("MarkAsset Successful");
        }

        public static void AutoMarkRootAddress(DirectoryInfo dir)
        {
            List<string> fileInfos = new List<string>();
            FilesUtils.GetFiles(dir.FullName, ref fileInfos);

            //检测用户config下是否存在config文件
            if (dir.Name == "Config")
            {
                List<string> fileNewInfos = new List<string>();
                foreach (var file in fileInfos)
                {
                    if (Path.GetExtension(file) != ".meta")
                    {
                        fileNewInfos.Add(file);
                    }
                }

                //不存在的配置对象名称
                List<string> configNonentity = new List<string>();
                //查找不存在的配置文件
                for (int i = 0; i < configNames.Length; i++)
                {
                    bool exists = false;
                    foreach (var filePath in fileNewInfos)
                    {
                        // 使用Path获取文件名
                        string fileName = Path.GetFileNameWithoutExtension(filePath);
                        if (fileName == configNames[i])
                        {
                            exists = true;
                            break;
                        }
                    }

                    if (!exists)
                    {
                        configNonentity.Add(configNames[i]);
                    }
                }

                string remotedRoot = Application.dataPath + "/Main/Config";
                List<string> mainConfigInfos = new List<string>();
                FilesUtils.GetFiles(remotedRoot, ref mainConfigInfos);
                //从main文件里拿取指定配置文件
                foreach (var config in configNonentity)
                {
                    foreach (var mainConfigInfo in mainConfigInfos)
                    {
                        // 使用Path获取文件名
                        string fileName = Path.GetFileNameWithoutExtension(mainConfigInfo);
                        if (Path.GetExtension(mainConfigInfo) != ".meta" && fileName.Equals(config))
                        {
                            fileInfos.Add(mainConfigInfo);
                            Debug.LogWarning($"用户资源目录不存在【{config}】文件，从Main目录下复制，此操作可能导致配置文件不完成，请在用户目录配置");
                            break;
                        }
                    }
                }
            }

            if (fileInfos != null && fileInfos.Count > 0)
            {
                foreach (var file in fileInfos)
                {
                    if (Path.GetExtension(file) != ".meta" && Path.GetExtension(file) != ".spriteatlas")
                    {
                        // string[] dirSplit = file.Split(new string[] { $"AddressableRes\\{dir.Name}\\" },
                        //     StringSplitOptions.RemoveEmptyEntries);
                        // string address = (dirSplit[dirSplit.Length - 1]).Replace("\\", "/");
                        // Debug.Log("address：" + address);
                        string groupName = dir.Name;
                        string assetPath = FilesUtils.AbsoluteToRelativePath("Assets", file); //Asset到文件的路径
                        var guid = AssetDatabase.AssetPathToGUID(assetPath);
                        var group = collectorGroupDic[groupName];
                        if (group != null)
                        {
                            AssetBundleCollector collector = new AssetBundleCollector()
                            {
                                CollectPath = assetPath,
                                CollectorGUID = guid,
                                CollectorType = ECollectorType.MainAssetCollector,
                                AddressRuleName = nameof(AddressByFolderAndFileName),
                                AssetTags = groupName,
                            };
                            //如果是video目录，设置
                            if (groupName == "Video")
                            {
                                collector.PackRuleName = nameof(PackVideoFile);
                            }

                            YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(group, collector);
                            Debug.Log("GetAssetAddress:" + GetAssetAddress(file));
                            AddAddressInfo(file, GetAssetAddress(file));
                        }
                        else
                        {
                            Debug.LogError("分组 = " + groupName + "不存在");
                        }
                    }
                }
            }
        }

        #region 图集

        public static void AutoCreateSpriteAtlas(string domainRootRes)
        {
            string AtlasRemotedRoot = domainRootRes + "/SpriteAtlas";
            string SpriteRemotedAtlas = domainRootRes + "/Sprites";
            DirectoryInfo[] remotedirs = new DirectoryInfo(SpriteRemotedAtlas).GetDirectories();
            foreach (var info in remotedirs)
            {
                AddSpriteAtlas(SpriteRemotedAtlas + "/" + info.Name, SpriteRemotedAtlas,
                    AtlasRemotedRoot, info);
            }
        }

        /// <summary>
        /// 自动创建图集
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="dir">文件夹</param>
        private static void AddSpriteAtlas(string path, string atlasRoot, string spriteAtlas, DirectoryInfo dir)
        {
            var groupname = "SpriteAtlas";
            var dirs = dir.GetDirectories();
            if (dirs == null || dirs.Length == 0)
            {
                string name = path.Replace(atlasRoot + "/", string.Empty).Replace("/", "_");
                string filePath = $"{spriteAtlas}/{name}.spriteatlas";
                // string[] dirSplit =
                //     filePath.Split(new string[] { $"AddressableRes/{Path.GetFileName(spriteAtlas)}" },
                //         StringSplitOptions.RemoveEmptyEntries);
                // string address = (dirSplit[dirSplit.Length - 1]).Substring(1).Replace("\\", "/");
                // Debug.Log("spriteatlasaddress：" + address);
                int assetIndex = filePath.IndexOf("Assets");
                string guidPath = filePath.Remove(0, assetIndex);
                if (!File.Exists(filePath))
                {
                    SpriteAtlas atlas = new SpriteAtlas();
                    //设置打包参数
                    SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings()
                    {
                        blockOffset = 1,
                        enableRotation = true,
                        enableTightPacking = false,
                        padding = 2,
                    };
                    atlas.SetPackingSettings(packSetting);

                    //设置打包后Texture图集信息
                    SpriteAtlasTextureSettings textureSettings = new SpriteAtlasTextureSettings()
                    {
                        readable = false,
                        generateMipMaps = false,
                        sRGB = true,
                        filterMode = FilterMode.Bilinear,
                    };
                    atlas.SetTextureSettings(textureSettings);

                    //设置平台图集大小压缩等信息
                    TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings()
                    {
                        maxTextureSize = 4096,
                        format = TextureImporterFormat.Automatic,
                        crunchedCompression = true,
                        textureCompression = TextureImporterCompression.Compressed,
                        compressionQuality = 50,
                    };
                    atlas.SetPlatformSettings(platformSettings);
                    AssetDatabase.CreateAsset(atlas, guidPath);
                    int pathIndex = path.IndexOf("Assets");
                    string spritePath = path.Remove(0, pathIndex);
                    UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(spritePath, typeof(UnityEngine.Object));
                    atlas.Add(new[] { obj });
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }

                var guid = AssetDatabase.AssetPathToGUID(guidPath);

                var group = collectorGroupDic[groupname];
                if (group != null)
                {
                    AssetBundleCollector collector = new AssetBundleCollector()
                    {
                        CollectPath = guidPath,
                        CollectorGUID = guid,
                        CollectorType = ECollectorType.MainAssetCollector,
                        AddressRuleName = nameof(AddressByFolderAndFileName),
                        AssetTags = groupname,
                    };
                    YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(group, collector);


                    AddAddressInfo(path, GetAssetAddress(path));
                }
                else
                {
                    Debug.LogError("分组 = " + GetAssetAddress(path) + "不存在");
                }

                AssetDatabase.Refresh();
            }
            else
            {
                if (dirs.Length > 0)
                {
                    foreach (var info in dirs)
                    {
                        AddSpriteAtlas(path + "/" + info.Name, atlasRoot, spriteAtlas, info);
                    }
                }
            }
        }

        #endregion

        private static void AddAddressInfo(string assetPath, string address)
        {
            if (addressDic.ContainsKey(assetPath))
            {
                Debug.LogError("命名重复,已经存在:" + assetPath);
            }
            else
            {
                addressDic.Add(assetPath, address);
            }
        }

        private static string GetAssetAddress(string assetPath)
        {
            string fileName = Path.GetFileNameWithoutExtension(assetPath);
            FileInfo fileInfo = new FileInfo(assetPath);
            return $"{fileInfo.Directory.Name}_{fileName}";
        }

        #endregion


        // /// <summary>
        // /// 标记是否有打包报错信息
        // /// </summary>
        // private static bool _isBuildSuccess = true;
        //
        // [MenuItem("Evo/BuildTools/BuildAdressable")]
        // private static void BuildByStatus()
        // {
        //     InitAssetData();
        //     _isBuildSuccess = true;
        //     //BuildTools.ClearConsole();
        //     Application.logMessageReceived += OnLogMessage;
        //
        //     AssetDatabase.Refresh();
        //     AssetDatabase.Refresh();
        //     MarkStatus();
        //     //SetMD5Info();
        //     AssetDatabase.Refresh();
        //     Application.logMessageReceived -= OnLogMessage;
        //     if (!_isBuildSuccess)
        //     {
        //         if (EditorUtility.DisplayDialog("打包失败", "请检测报错信息", "确定"))
        //         {
        //             // EditorUtility.RevealInFinder(BuildTools.OutPath);
        //             // BuildTools.OutPath = string.Empty;
        //         }
        //     }
        // }


        /// <summary>
        /// 标记为资源分组
        /// </summary>
        private static void MarkStatus()
        {
            List<AssetBundleCollectorGroup> deleteList = new List<AssetBundleCollectorGroup>();
            for (int i = 0; i < package.Groups.Count; i++)
            {
                var group = package.Groups[i];
                if (group.GroupName != "Default Local Group" && group.GroupName != "Built In Data")
                {
                    if (group.Collectors.Count <= 0)
                    {
                        ///删除没有资源的分组
                        deleteList.Add(group);
                    }
                }
            }

            for (int i = 0; i < deleteList.Count; i++)
            {
                package.Groups.Remove(deleteList[i]);
            }
        }

        // private static Dictionary<string, MD5Info> _md5Files = new Dictionary<string, MD5Info>();
        //
        // private static void SetMD5Info()
        // {
        //     _md5Files.Clear();
        //
        //     string path = Application.dataPath.Replace("Assets",
        //         $"ServerData/{Application.platform}/Release");
        //     if (Directory.Exists(path))
        //     {
        //         DirectoryInfo dir = new DirectoryInfo(path);
        //         MD5File(dir);
        //     }
        //
        //     AssetDatabase.Refresh();
        // }
        //
        // private static void MD5File(DirectoryInfo info)
        // {
        //     FileInfo[] files = info.GetFiles();
        //     if (files.Length > 0)
        //     {
        //         for (int i = 0; i < files.Length; i++)
        //         {
        //             var file = files[i];
        //             if (file == null || file.Extension == ".meta")
        //             {
        //                 continue;
        //             }
        //
        //             string filePath = file.FullName.Replace(@"\", "/");
        //             MD5Info md5 = new MD5Info();
        //             md5.AssetPath = filePath;
        //             md5.MD5 = FilesUtils.CalculateMD5(file.FullName);
        //             _md5Files.Add(md5.AssetPath, md5);
        //         }
        //     }
        //
        //     DirectoryInfo[] dirs = info.GetDirectories();
        //     if (dirs != null && dirs.Length > 0)
        //     {
        //         for (int i = 0; i < dirs.Length; i++)
        //         {
        //             MD5File(dirs[i]);
        //         }
        //     }
        // }

        // private static void OnLogMessage(string condition, string stackTrace, LogType type)
        // {
        //     if (type == LogType.Error)
        //     {
        //         if (condition != "EndLayoutGroup: BeginLayoutGroup must be called first.")
        //             _isBuildSuccess = false;
        //     }
        // }
    }
}