using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using WS;

///<summary>通用方法</summary>
public static class EditorHelper
{
    ///<summary>拷贝文件</summary>
    ///<param name="srcDir">操作文件夹</param>
    ///<param name="tgtDir">目标文件夹</param>
    public static void CopyDirectory(string srcDir, string tgtDir)
    {
        DirectoryInfo source = new DirectoryInfo(srcDir);
        DirectoryInfo target = new DirectoryInfo(tgtDir);

        if (target.FullName.StartsWith(source.FullName, StringComparison.CurrentCultureIgnoreCase))
            throw new Exception("父目录不能拷贝到子目录！");

        if (!source.Exists)
            return;

        if (!target.Exists)
            target.Create();

        FileInfo[] files = source.GetFiles();
        for (int i = 0; i < files.Length; i++)
        {
            File.Copy(files[i].FullName, Path.Combine(target.FullName, files[i].Name), true);
        }

        DirectoryInfo[] dirs = source.GetDirectories();
        for (int j = 0; j < dirs.Length; j++)
        {
            CopyDirectory(dirs[j].FullName, Path.Combine(target.FullName, dirs[j].Name));
        }
    }

    ///<summary>获取真实Resources路径</summary>
    public static (bool, string) GetPath(string assetpath)
    {
        assetpath = assetpath.Split('.')[0];
        List<string> files = assetpath.Split('/').ToList();
        if (files.Exists(f => f == "Resources"))
        {
            string rpath = "";
            int startindex = files.FindIndex(f => f == "Resources");
            for (int i = 0; i < files.Count; i++)
            {
                if (i >= startindex + 1)
                {
                    rpath += files[i];
                    if (i < files.Count - 1)
                    {
                        rpath += "/";
                    }
                }
            }
            return (true, rpath);
        }
        return (false, "资源不在Resources文件夹下");
    }

    /// <summary>获取所有同类型资源</summary>
    /// <typeparam name="T">资源类型</typeparam>
    /// <param name="filter">资源类型命名规则</param>
    /// <param name="error">错误信息 [文本规则:场景 {0} 重复,项目中场景名称不能重复!]</param>
    public static Dictionary<string, T> GetAssetData<T>(string filter, string error) where T : UnityEngine.Object
    {
        Dictionary<string, T> disobject = new Dictionary<string, T>();
        string[] files = AssetDatabase.FindAssets(filter);
        for (int i = 0; i < files.Length; i++)
        {
            files[i] = AssetDatabase.GUIDToAssetPath(files[i]);
            string fileName = Path.GetFileNameWithoutExtension(files[i]);
            T scene = AssetDatabase.LoadAssetAtPath<T>(files[i]);
            if (disobject.ContainsKey(fileName))
            {
                error = string.Format(error, fileName);
                Debug.LogError(error);
            }
            else
            {
                disobject.Add(fileName, scene);
            }
        }
        return disobject;
    }

    ///<summary>获取物体相对路径</summary>
    public static string GetTransformParentPath(Transform trans)
    {
        string path = "";
        Transform[] transforms = trans.transform.GetComponentsInParent<Transform>();
        for (int i = transforms.Length - 1; i >= 0; i--)
        {
            if (i == transforms.Length - 1)
            {
                path += transforms[i].name;
            }
            else
            {
                path += "/" + transforms[i].name;
            }
        }
        return path;
    }

    /// <summary>创建相机注视物体</summary>
    /// <param name="ObjName">物体名称</param>
    public static GameObject CreateLookObj(string ObjName, Vector3 pos, Vector3 rot)
    {
        TextMesh look = GameObject.Instantiate(AssetDatabase.LoadAssetAtPath<TextMesh>("Assets/GameResources/Prefabs/Item/Look"));
        look.transform.position = pos;
        look.transform.eulerAngles = rot;
        look.text = $"{ObjName}-相机移动目标点";
        return look.gameObject;
    }

    ///<summary>获取动画片段</summary>
    public static string[] GetClips(GameObject animobj)
    {
        Animator animator = animobj.GetComponent<Animator>();
        AnimationClip[] clips = animator.runtimeAnimatorController.animationClips;
        string[] Clips = new string[clips.Length];
        for (int i = 0; i < clips.Length; i++)
        {
            Clips[i] = clips[i].name;
        }
        return Clips;
    }

    ///<summary>获取所有子类类型</summary>
    public static List<Type> GetAllChildType<T>() where T : class
    {
        List<Type> alltype = new List<Type>();
        Type type = typeof(T);
        Type[] types = type.Assembly.GetTypes();
        for (int i = 0; i < types.Length; i++)
        {
            if (types[i].BaseType == type)
            {
                alltype.Add(types[i]);
            }
        }
        return alltype;
    }

    ///<summary>类型-转为脚本</summary>
    public static void TypeToScript<T>(string path, Type type) where T : WSComponent
    {
        path = $"{path}/{type.Name}_partial.cs";
        using (FileStream fileStream = new FileStream(path, FileMode.Create))
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("");
            sb.AppendLine("namespace WS");
            sb.AppendLine("{");
            sb.AppendLine($"    ///<summary>{type.Name}扩展</summary>");
            sb.AppendLine($"    public partial class {type.Name}");
            sb.AppendLine("    {");
            sb.AppendLine("        ///<summary>初始化类型To名称</summary>");
            sb.AppendLine("        private Dictionary<Type, string> DicTypeToName = new Dictionary<Type, string>();");
            sb.AppendLine("");
            sb.AppendLine("        private void StartType()");
            sb.AppendLine("        {");
            List<Type> types = EditorHelper.GetAllChildType<T>();
            for (int i = 0; i < types.Count; i++)
            {
                sb.AppendLine($"            DicTypeToName.Add(typeof({types[i].Name}), \"{types[i].Name}\");");
            }
            sb.AppendLine("        }");
            sb.AppendLine("");
            sb.AppendLine("        ///<summary>获取名称</summary>");
            sb.AppendLine("        private string GetToName(Type type)");
            sb.AppendLine("        {");
            sb.AppendLine("            return DicTypeToName[type];");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            string str = sb.ToString();
            byte[] bytes = str.ToByteArray();
            fileStream.Write(bytes, 0, bytes.Length);
            sb.Clear();
        }
    }

    ///<summary>名称-转为脚本</summary>
    public static void NameToScript(string path, Type type, List<Type> types)
    {
        path = $"{path}/{type.Name}_partial.cs";
        using (FileStream fileStream = new FileStream(path, FileMode.Create))
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("");
            sb.AppendLine("namespace WS");
            sb.AppendLine("{");
            sb.AppendLine($"    ///<summary>{type.Name}扩展</summary>");
            sb.AppendLine($"    public partial class {type.Name}");
            sb.AppendLine("    {");
            sb.AppendLine("        ///<summary>初始化名称To类型</summary>");
            sb.AppendLine("        private Dictionary<string, Type> DicNameToType = new Dictionary<string, Type>();");
            sb.AppendLine("");
            sb.AppendLine("        private void StartType()");
            sb.AppendLine("        {");
            for (int i = 0; i < types.Count; i++)
            {
                sb.AppendLine($"            DicNameToType.Add(\"{types[i].Name}\", typeof({types[i].Name}));");
            }
            sb.AppendLine("        }");
            sb.AppendLine("");
            sb.AppendLine("        ///<summary>获取名称</summary>");
            sb.AppendLine("        private Type GetToType(string name)");
            sb.AppendLine("        {");
            sb.AppendLine("            return DicNameToType[name];");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            string str = sb.ToString();
            byte[] bytes = str.ToByteArray();
            fileStream.Write(bytes, 0, bytes.Length);
            sb.Clear();
        }
    }

    ///<summary>名称-转为脚本</summary>
    public static void NameToScript<T>(string path, Type type) where T : WSComponent
    {
        path = $"{path}/{type.Name}_partial.cs";
        using (FileStream fileStream = new FileStream(path, FileMode.Create))
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("");
            sb.AppendLine("namespace WS");
            sb.AppendLine("{");
            sb.AppendLine($"    ///<summary>{type.Name}扩展</summary>");
            sb.AppendLine($"    public partial class {type.Name}");
            sb.AppendLine("    {");
            sb.AppendLine("        ///<summary>初始化名称To类型</summary>");
            sb.AppendLine("        private Dictionary<string, Type> DicNameToType = new Dictionary<string, Type>();");
            sb.AppendLine("");
            sb.AppendLine("        private void StartType()");
            sb.AppendLine("        {");
            List<Type> types = EditorHelper.GetAllChildType<T>();
            for (int i = 0; i < types.Count; i++)
            {
                sb.AppendLine($"            DicNameToType.Add(\"{types[i].Name}\", typeof({types[i].Name}));");
            }
            sb.AppendLine("        }");
            sb.AppendLine("");
            sb.AppendLine("        ///<summary>获取名称</summary>");
            sb.AppendLine("        private Type GetToType(string name)");
            sb.AppendLine("        {");
            sb.AppendLine("            return DicNameToType[name];");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            string str = sb.ToString();
            byte[] bytes = str.ToByteArray();
            fileStream.Write(bytes, 0, bytes.Length);
            sb.Clear();
        }
    }
}