using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Object = UnityEngine.Object;

namespace TFramework
{
    /// <summary>
    /// 编辑器全局工具类
    /// </summary>
    public class EditorGlobalTool
    {
        public static Folder Code = new Folder(null, "Code", "Scenes");
        public static Folder[] ProjectStructureFolder = new Folder[]
        {
            new Folder(null,"Plugins"),
            new Folder(null,"Ued","Scenes","Model","UI","Materials","Textures","Animations","Sound","Fonts","Video","Prefabs"),
            new Folder(null,"StreamingAssets","PDF","JSON","TEXT")
        };
        public static Folder Env1 = new Folder(Code, "Env1", "Scripts", "Animations", "Animators", "Audios", "Materials", "Fonts", "FX", "Shaders", "Sprites", "Textures", "Prefabs", "Resources", "Data");
        public static Folder DataFolder = new Folder(Env1, "Editor", "Data");
        #region 工具
        /// <summary>
        /// 快捷构建项目结构
        /// </summary>
        [MenuItem("Assets/Create/TFramework/构建项目结构", false, 2)]
        public static void CreateProjectStructure()
        {
            CreateFolder(Code);
            for (int i = 0; i < ProjectStructureFolder.Length; i++)
                CreateFolder(ProjectStructureFolder[i]);
            CreateFolder(Env1);
            CreateFolder(DataFolder);
        }

        private static void CreateFolder(Folder folder)
        {
            if (!AssetDatabase.IsValidFolder(folder.Path))
            {
                AssetDatabase.CreateFolder(folder.Parent != null ? folder.Parent.Path : "Assets", folder.Name);
            }
            for (int i = 0; i < folder.SubFolders.Count; i++)
            {
                CreateFolder(folder.SubFolders[i]);
            }
        }


        [MenuItem("TFramework/Tools/一键清理缺失脚本")]
        public static void CleanMissingScript()
        {
            int sum = 0;
            GameObject[] gos = Selection.gameObjects;
            for (int i = 0; i < gos.Length; i++)
            {
                foreach (var item in gos[i].GetComponentsInChildren<Transform>(true))
                {
                    if(GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(item.gameObject)>0)
                    {
                        int r = 0;
                        r = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(item.gameObject);
                        if (PrefabUtility.GetPrefabAssetType(item.gameObject) != PrefabAssetType.NotAPrefab)
                        {
                            PrefabUtility.SaveAsPrefabAssetAndConnect(item.gameObject, GetPrefabAssetPath(item.gameObject), InteractionMode.AutomatedAction);
                            AssetDatabase.Refresh();
                        }
                        else
                        {
                            EditorUtility.SetDirty(item);
                            AssetDatabase.Refresh();
                        }

                        sum += r;
                        Log.Info("清除了物体：" + item.name + " 的一个missing脚本");
                    }
                }
            }
            Log.Info("清除完成,清理个数：" + sum);
        }

        #endregion

        #region 创建脚本

        [MenuItem("Assets/Create/TFramework/创建UIScript", false, 100)]
        public static void CreateUIScript()
        {
            CreateScriptFromTemplate.Create<CreateGeneralScript>(EditorConfigFile.CreateUIScriptTemplatePath, "NewUIScript",
                EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D);
        }

        [MenuItem("Assets/Create/创建C# Script", false, 80)]
        public static void CreateScript()
        {
            CreateScriptEdit.OpenWin();
        }
        #endregion


        #region 快捷操作
        static GenericMenu pathMenu;
        [MenuItem("GameObject/TFramework/拷贝层级路径", false, 20)]
        public static void GetObjPath()
        {
            EditorApplication.delayCall -= ShowCustomMenu;
            EditorApplication.delayCall += ShowCustomMenu;
        }

        private static void ShowCustomMenu()
        {
            Transform obj = Selection.activeTransform;
            Transform parent = obj.parent;
            pathMenu = new GenericMenu();
            string path = obj.name;
            while (parent != null)
            {
                path = parent.name + "/" + path;
                parent = parent.parent;
                string p = path.Replace("/", ">");
                pathMenu.AddItem(new GUIContent(p), false, () =>
                {
                    GUIUtility.systemCopyBuffer = p.Replace(">", "/");
                });
            }
            var window = EditorWindow.focusedWindow;
            if (window != null)
            {
                // 获取窗口视图的中心点
                Vector2 centerPosition = new Vector2(window.position.width / 2, window.position.height / 2);
                pathMenu.DropDown(new Rect(centerPosition, Vector2.zero));
            }
        }
        #endregion


        #region 代码调用
        private static HashSet<string> EditorAssemblies = new HashSet<string>()
        {
            "Assembly-CSharp-Editor","UnityEditor","UnityEditor.SceneManagement","UnityEditorInternal","TFramework.Editor","UnityEditor.CoreModule"
        };
        /// <summary>
        /// 获取编辑器程序集中所有类型
        /// </summary>
        /// <returns></returns>
        public static List<Type> GetTypeInEditorAssemblies()
        {
            List<Type> types = new List<Type>();
            Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < assemblys.Length; i++)
            {
                if (EditorAssemblies.Contains(assemblys[i].GetName().Name))
                {
                    types.AddRange(assemblys[i].GetTypes());
                }
            }
            return types;
        }

        /// <summary>
        /// 获取编辑器程序集中符合条件的类型
        /// </summary>
        /// <param name="filter">条件</param>
        /// <returns></returns>
        public static List<Type> GetTypeInEditorAssemblies(TFunc<Type, bool> filter)
        {
            List<Type> types = new List<Type>();
            Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < assemblys.Length; i++)
            {
                if (EditorAssemblies.Contains(assemblys[i].GetName().Name))
                {
                    Type[] ts = assemblys[i].GetTypes();
                    foreach (var t in ts)
                    {
                        if (filter(t))
                        {
                            types.Add(t);
                        }
                    }
                }
            }
            return types;
        }

        /// <summary>
        /// 获取编辑器程序集中的类型
        /// </summary>
        /// <returns></returns>
        public static Type GetTypeInEditorAssemblies(string space,string typeName)
        {
            Type type = null;
            Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < assemblys.Length; i++)
            {
                if (EditorAssemblies.Contains(assemblys[i].GetName().Name)&& assemblys[i].GetName().Name==space)
                {
                    Type[] ts = assemblys[i].GetTypes();
                    foreach (var t in ts)
                    {
                        if (t.Name==typeName)
                        {
                            type=t;
                        }
                    }
                }
            }
            return type;
        }

        /// <summary>
        /// 获取编辑器程序集中符合条件的方法
        /// </summary>
        /// <param name="filter">条件</param>
        /// <returns></returns>
        public static List<MethodInfo> GetMethodInEditorAssemblies(TFunc<MethodInfo, bool> filter)
        {
            List<MethodInfo> methodInfos = new List<MethodInfo>();
            Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < assemblys.Length; i++)
            {
                if (EditorAssemblies.Contains(assemblys[i].GetName().Name))
                {
                    foreach (var item in assemblys[i].GetTypes())
                    {
                        methodInfos.AddRange(item.GetMethods(filter));
                    }
                }
            }
            return methodInfos;
        }

        public static MethodInfo GetMethodInEditorAssemblie(string typeFullName,string methodName)
        {
            MethodInfo method = null;
            Type type = Type.GetType(typeFullName);
            if(type!=null)
                method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
            return method;
        }

        /// <summary>
        /// 获取Hierarchy预制体在Project路径
        /// </summary>
        /// <param name="gameObject">预制体</param>
        /// <returns></returns>
        public static string GetPrefabAssetPath(GameObject gameObject)
        {
            string path = "";
            if (PrefabUtility.IsPartOfPrefabAsset(gameObject))
                path = AssetDatabase.GetAssetPath(gameObject);
            else if(PrefabUtility.IsPartOfPrefabInstance(gameObject))
            {
                GameObject go = PrefabUtility.GetCorrespondingObjectFromOriginalSource(gameObject);
                path = AssetDatabase.GetAssetPath(go);
            }
            else
            {
                var prefab = PrefabStageUtility.GetPrefabStage(gameObject);
                if (prefab != null)
                    path = prefab.assetPath;
            }
            return path;
        }

        /// <summary>
        /// 添加自定义宏
        /// </summary>
        /// <param name="symbol"></param>
        public static void AddDefineSymbols(string symbol)
        {
            BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
            string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
            if (symbols.Split(';').Contains(symbol)) return;
            symbols = string.IsNullOrEmpty(symbols) ? symbol : symbols += $";{symbol}";
            PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, symbols);
        }

        /// <summary>
        /// 移除自定义宏
        /// </summary>
        /// <param name="symbol"></param>
        public static void RemoveDefineSymbols(string symbol)
        {
            BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
            string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
            List<string> symbolList = new List<string>(symbols.Split(';'));

            if (symbolList.Contains(symbol))
            {
                symbolList.Remove(symbol);
            }
            symbols = "";
            symbolList.ForEach(p => symbols += p + ";");
            PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, symbols);
        }

        #endregion
    }
    public class Folder
    {
        public Folder Parent;
        public List<Folder> SubFolders;
        public string Name;
        public string Path;
        public string FullPath;

        public Folder(Folder parent, string name, params string[] subs)
        {
            Parent = parent;
            SubFolders = new List<Folder>();
            Name = name;
            Path = Parent == null ? ("Assets/" + Name) : (Parent.Path + "/" + Name);
            FullPath = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("/")) + "/" + Path;

            if (Parent != null)
            {
                Parent.SubFolders.Add(this);
            }
            for (int i = 0; i < subs.Length; i++)
            {
                new Folder(this, subs[i]);
            }
        }
    }
}
