/****************************************************
 文件：EditorFrameworkUtils.cs
 作者：张铮
 邮箱：
 日期：2022/3/8 17:50:17
 功能：
*****************************************************/

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

namespace Stary.Evo.Editor
{
#if UNITY_EDITOR
    /// <summary>
    ///     文件辅助类
    /// </summary>
    public static class FilesUtils
    {
        /// <summary>
        ///     编码方式
        /// </summary>
        private static readonly Encoding Encoding = Encoding.UTF8;

        /// <summary>
        ///     递归取得文件夹下文件
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="list"></param>
        /// <param name="fileExtsions"></param>
        public static void GetFiles(string dir, ref List<string> list)
        {
            //添加文件 
            string[] files = Directory.GetFiles(dir);
            //if (fileExtsions.Count > 0)
            //{
            foreach (string file in files)
            {
                string extension = Path.GetExtension(file);
                if (extension != null)
                {
                    list.Add(file);
                }
            }

            // }
            // else
            // {
            //     list.AddRange(files);
            // }
            //如果是目录，则递归
            DirectoryInfo[] directories = new DirectoryInfo(dir).GetDirectories();
            foreach (DirectoryInfo item in directories)
            {
                GetFiles(item.FullName, ref list);
            }
        }

        /// <summary>
        /// 创建文件夹
        /// </summary>
        public static void CreateFolder()
        {
            //  Directory.CreateDirectory();//
        }

        /// <summary>
        ///     写入文件
        /// </summary>
        /// <param name="filePath">文件名</param>
        /// <param name="content">文件内容</param>
        public static void WriteFile(string filePath, string content)
        {
            try
            {
                var fs = new FileStream(filePath, FileMode.Create);
                Encoding encode = Encoding;
                //获得字节数组
                byte[] data = encode.GetBytes(content);
                //开始写入
                fs.Write(data, 0, data.Length);
                //清空缓冲区、关闭流
                fs.Flush();
                fs.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        ///     读取文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string ReadFile(string filePath)
        {
            return ReadFile(filePath, Encoding);
        }

        /// <summary>
        ///     读取文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string ReadFile(string filePath, Encoding encoding)
        {
            using (var sr = new StreamReader(filePath, encoding))
            {
                return sr.ReadToEnd();
            }
        }

        /// <summary>
        ///     读取文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static List<string> ReadFileLines(string filePath)
        {
            var str = new List<string>();
            using (var sr = new StreamReader(filePath, Encoding))
            {
                String input;
                while ((input = sr.ReadLine()) != null)
                {
                    str.Add(input);
                }
            }

            return str;
        }

        /// <summary>
        /// 文件复制
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="targetPath"></param>
        public static void CopyFile(string filePath, string targetPath)
        {
            FileInfo file = new FileInfo(filePath);
            if (!Directory.Exists(targetPath))
            {
                Directory.CreateDirectory(targetPath);
            }

            if (file != null)
            {
                string tempPath = Path.Combine(targetPath, file.Name);
                file.CopyTo(tempPath, true); //如果文件存在则覆盖
            }
        }

        /// <summary>
        ///     复制文件夹（及文件夹下所有子文件夹和文件）
        /// </summary>
        /// <param name="sourcePath">待复制的文件夹路径</param>
        /// <param name="destinationPath">目标路径</param>
        public static void CopyDirectory(String sourcePath, String destinationPath)
        {
            var info = new DirectoryInfo(sourcePath);
            Directory.CreateDirectory(destinationPath);
            foreach (FileSystemInfo fsi in info.GetFileSystemInfos())
            {
                String destName = Path.Combine(destinationPath, fsi.Name);

                if (fsi is FileInfo) //如果是文件，复制文件
                    File.Copy(fsi.FullName, destName);
                else //如果是文件夹，新建文件夹，递归
                {
                    Directory.CreateDirectory(destName);
                    CopyDirectory(fsi.FullName, destName);
                }
            }
        }

        /// <summary>
        ///     删除文件夹（及文件夹下所有子文件夹和文件）
        /// </summary>
        /// <param name="directoryPath"></param>
        public static void DeleteFolder(string directoryPath)
        {
            foreach (string d in Directory.GetFileSystemEntries(directoryPath))
            {
                if (File.Exists(d))
                {
                    var fi = new FileInfo(d);
                    if (fi.Attributes.ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
                        fi.Attributes = FileAttributes.Normal;
                    File.Delete(d); //删除文件   
                }
                else
                    DeleteFolder(d); //删除文件夹
            }

            Directory.Delete(directoryPath); //删除空文件夹
        }

        /// <summary>
        ///     清空文件夹（及文件夹下所有子文件夹和文件）
        /// </summary>
        /// <param name="directoryPath"></param>
        public static void ClearFolder(string directoryPath)
        {
            foreach (string d in Directory.GetFileSystemEntries(directoryPath))
            {
                if (File.Exists(d))
                {
                    var fi = new FileInfo(d);
                    if (fi.Attributes.ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
                        fi.Attributes = FileAttributes.Normal;
                    File.Delete(d); //删除文件   
                }
                else
                    DeleteFolder(d); //删除文件夹
            }
        }

        /// <summary>
        ///     取得文件大小，按适当单位转换
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static string GetFileSize(string filepath)
        {
            string result = "0KB";
            if (File.Exists(filepath))
            {
                var size = new FileInfo(filepath).Length;
                int filelength = size.ToString().Length;
                if (filelength < 4)
                    result = size + "byte";
                else if (filelength < 7)
                    result = Math.Round(Convert.ToDouble(size / 1024d), 2) + "KB";
                else if (filelength < 10)
                    result = Math.Round(Convert.ToDouble(size / 1024d / 1024), 2) + "MB";
                else if (filelength < 13)
                    result = Math.Round(Convert.ToDouble(size / 1024d / 1024 / 1024), 2) + "GB";
                else
                    result = Math.Round(Convert.ToDouble(size / 1024d / 1024 / 1024 / 1024), 2) + "TB";
                return result;
            }

            return result;
        }

        /// <summary>
        ///     删除文件.
        /// </summary>
        /// <param name="path">删除完整文件夹路径.</param>
        /// <param name="name">删除文件的名称.</param>
        public static void DeleteFile(string path, string name)
        {
            File.Delete(path + name);
        }

        /// <summary>
        ///     删除文件夹下所有子文件夹与文件
        /// </summary>
        public static void DeleteAllChild(string path, FileAttributes filter)
        {
            if (!Directory.Exists(path))
                return;

            DirectoryInfo dir = new DirectoryInfo(path);
            FileInfo[] files = dir.GetFiles("*");
            for (int i = 0; i < files.Length; ++i)
            {
                if ((files[i].Attributes & filter) > 0)
                    continue;
                if (File.Exists(files[i].FullName))
                    File.Delete(files[i].FullName);
            }

            DirectoryInfo[] dirs = dir.GetDirectories("*");
            for (int i = 0; i < dirs.Length; ++i)
            {
                if ((dirs[i].Attributes & filter) > 0)
                    continue;

                if (Directory.Exists(dirs[i].FullName))
                    Directory.Delete(dirs[i].FullName, true);
            }
        }

        /// <summary>
        ///     绝对路径转相对路径
        /// </summary>
        public static string AbsoluteToRelativePath(string root_path, string absolute_path)
        {
            absolute_path = absolute_path.Replace('\\', '/');
            int last_idx = absolute_path.LastIndexOf(root_path);
            if (last_idx < 0)
                return absolute_path;

            int start = last_idx;
            if (absolute_path[start] == '/')
                start += 1;

            int length = absolute_path.Length - start;
            return absolute_path.Substring(start, length);
        }

        /// <summary>
        ///     获得取除路径扩展名的路径
        /// </summary>
        public static string GetPathWithoutExtension(this string full_name)
        {
            int last_idx = full_name.LastIndexOfAny(".".ToCharArray());
            if (last_idx < 0)
                return full_name;

            return full_name.Substring(0, last_idx);
        }

        /// <summary>
        /// 将字符串转为大写或小写
        /// </summary>
        /// <param name="tmp"></param>
        /// <param name="isUpper"></param>
        /// <returns></returns>
        public static string GetUpperOrLower(this string tmp, bool isUpper = true)
        {
            if (isUpper)
                return tmp.ToLower();
            else
                return tmp.ToUpper();
        }

        /// <summary>
        /// 判断是否有中文，有转为全拼
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string ChineseToPinYin(string text, bool isfile = true)
        {
            if (HasChinese(text))
            {
                return ConvertPinYin(text, isfile).GetUpperOrLower().Replace(" ", "");
            }
            else
            {
                if (isfile)
                    text = String.Concat("_", text);
                return text.GetUpperOrLower();
            }
        }

        /// <summary>
        /// 判断字符串中是否有中文
        /// </summary>
        private static bool HasChinese(string s)
        {
            return Regex.IsMatch(s, "[\u4e00-\u9fbb]");
        }

        /// <summary>
        /// 汉字转全拼
        /// </summary>
        private static string ConvertPinYin(string text, bool isfile = true)
        {
            if (string.IsNullOrEmpty(text))
                return text;

            try
            {
                var sb = new StringBuilder();
                bool isfirstchinese = false;
                if (HasChinese(text.ToList()[0].ToString()))
                {
                    isfirstchinese = true;
                    Debug.Log(text.ToList()[0].ToString() + ":" + isfirstchinese);
                }

                for (int i = 0; i < text.ToList().Count; i++)
                {
                    if (text.ToList()[i] <= 127)
                        sb.Append(text.ToList()[i]);
                    else
                        sb.Append($"_{NPinyin.Pinyin.GetPinyin(text.ToList()[i])}_");
                }

                var name = sb.ToString().Replace("__", "_");
                if (!isfile) //裁剪首尾字符“_”
                {
                    name = name.Trim('_');
                }
                else
                {
                    name = name.TrimEnd('_');
                    if (!isfirstchinese)
                        name = String.Concat("_", name);
                }

                return name;
            }
            catch (Exception e)
            {
                Debug.LogError($"拼音转换失败：{text}  {e.Message}");
            }

            return text;
        }

        /// <summary>
        /// 删除指定字符后的字符串
        /// </summary>
        /// <param name="fileName">字符串</param>
        /// <param name="lastIndex">符号例如：“ .”</param>
        /// <returns></returns>
        public static string DeleteLastIndex(string fileName, string lastIndex)
        {
            int index = fileName.LastIndexOf(lastIndex);
            if (index >= 0)
            {
                fileName = fileName.Substring(0, index);
            }

            return fileName;
        }

        /// <summary>
        /// 带颜色的日志输出
        /// </summary>
        public static void LogColor(string s, string path = null, Color color = default)
        {
            if (string.IsNullOrEmpty(path))
                Debug.Log($"<color=#{ColorUtility.ToHtmlStringRGB(color)}>{s}</color>");
            else
            {
                string assetPath = s.Replace("\\", "/").Replace(Application.dataPath, "Assets");
                Debug.Log($"<color=#{ColorUtility.ToHtmlStringRGB(color)}>{assetPath}</color>",
                    AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath));
            }
        }

        /// <summary>
        /// 过滤：去掉首尾空格和换行符【\n】
        /// </summary>
        private static string FilterTo(string self)
        {
            self = self.TrimStart();
            self = self.TrimEnd();
            self = self.Replace("\n", "");
            return self;
        }

        /// <summary>
        /// 获取Assets下带.meta文件的资源的路径
        /// </summary>
        /// <param name="objectName">文件夹、资源</param>
        private static string[] GetPathsOfAssetsObject(string objectName)
        {
            string[] guids = AssetDatabase.FindAssets(objectName);
            string[] paths = new string[guids.Length];
            for (int i = 0; i < guids.Length; i++)
            {
                string path = AssetDatabase.GUIDToAssetPath(guids[i]);
                if (path.Contains("Assets"))
                    paths[i] = path;
            }

            return paths;
        }

        /// <remarks>计算MD5</remarks>
        public static string CalculateMD5(string file)
        {
            string result = "";
            FileStream fs = new FileStream(file, FileMode.Open);
            try
            {
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(fs);
                fs.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }

                result = sb.ToString();
            }
            catch (Exception e)
            {
                UnityEngine.Debug.Log("md5file() fail, error:" + e.Message);
            }
            finally
            {
                fs.Close();
            }

            return result;
        }
    }
#endif
}