using XGame.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;

namespace XGame.Editor.Asset
{
    public static class FileUtil
    {
        ///// <summary>
        ///// 收集指定路径下的指定后缀的文件
        ///// </summary>
        ///// <param name="rootPath"></param>
        ///// <param name="patterns"></param>
        ///// <param name="isFindSelected"></param>
        ///// <returns></returns>
        //public static List<string> CollectFiles(string rootPath, string[] patterns, bool isFindSelected)
        //{
        //    List<string> allFiles = new List<string>();

        //    if (!Directory.Exists(rootPath))
        //        return allFiles;

        //    foreach (var pattern in patterns)
        //    {
        //        var files = Directory.GetFiles(rootPath, pattern, SearchOption.AllDirectories);
        //        foreach (var file in files)
        //            allFiles.Add(file.Replace("\\", "/"));
        //    }
        //    // 只对选择物体打包
        //    if (isFindSelected)
        //    {
        //        // 返回一个交集 就是判断当前选择是否满足条件
        //        return allFiles.Intersect(Selection.objects.Select(AssetDatabase.GetAssetPath)).ToList();
        //    }
        //    else
        //    {
        //        return allFiles;
        //    }
        //}

        /// <summary>
        /// 贴图文件后缀
        /// </summary>
        public static readonly string[] texturePatterns = { ".png", ".jpg", ".tga", ".psd" };
        private static readonly string textureExts = ".png.jpg.tga.psd";
        /// <summary>
        /// 图集配置文件后缀
        /// </summary>
        public static readonly string spriteatlasPattern = ".spriteatlas";

        /// <summary>
        /// 文件是否是Texture
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool IsTextureFile(string filePath)
        {
            var ext = Path.GetExtension(filePath);
            return string.IsNullOrEmpty(ext) == false && textureExts.Contains(ext, StringComparison.OrdinalIgnoreCase);
        }
        /// <summary>
        /// 是否是SpriteAtlas文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool IsSpriteAtlas(string filePath)
        {
            return filePath.EndsWith(spriteatlasPattern, StringComparison.OrdinalIgnoreCase);
        }
        /// <summary>
        /// 查找指定文件夹下的指定类型的文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="patterns">文件后缀名</param>
        /// <param name="option"></param>
        /// <returns></returns>
        public static string[] FindFiles(string path, string[] patterns, SearchOption option = SearchOption.AllDirectories)
        {
            if (!Directory.Exists(path) || patterns == null)
            {
                return new string[0];
            }
            var files = Directory.GetFiles(path, "*.*", option).Where(file =>
            {
                foreach (var pattern in patterns)
                {
                    if (file.EndsWith(pattern))
                    {
                        return true;
                    }
                }
                return false;
            }).ToArray();
            for (var i = 0; i < files.Length; i++)
            {
                files[i] = files[i].Replace("\\", "/");
            }
            return files;
        }
        /// <summary>
        /// 查找指定文件夹下的指定类型的文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="pattern">必须使用"*."开头</param>
        /// <param name="option"></param>
        /// <returns></returns>
        public static string[] FindFiles(string path, string pattern, SearchOption option = SearchOption.AllDirectories)
        {
            if (!Directory.Exists(path) || string.IsNullOrEmpty(pattern))
            { //文件夹不存在或后缀名为空
                return new string[0];
            }
            //必须使用"*."开头
            if (pattern.StartsWith("."))
            {
                pattern = $"*{pattern}";
            }
            var files = Directory.GetFiles(path, pattern, option);
            for (var i = 0; i < files.Length; i++)
            {
                files[i] = files[i].Replace("\\", "/");
            }
            return files;
        }

        /// <summary>
        /// 查找指定路径下的所有文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string[] FindFiles(string path)
        {
            List<string> lst = new List<string>();
            FindFiles(path, (files) =>
            {
                lst.AddRange(files);
            });
            return lst.ToArray();
        }

        /// <summary>
        /// 查找指定路径下的所有文件，按照所在文件夹批次返回结果
        /// path为全路径，则返回的也是全路径
        /// path为AssetPath，则返回的也是AssetPath
        /// </summary>
        /// <param name="path"></param>
        /// <param name="action"></param>
        public static void FindFiles(string path, System.Action<string[]> action)
        {
            var lst = new List<string>();
            var files = Directory.GetFiles(path).Where((file) => !IsFileIgnore(file)).ToArray();
            if (files.Length > 0 && action != null)
            {
                for (var i = 0; i < files.Length; i++)
                {
                    files[i] = files[i].Replace("\\", "/");
                }
                action.Invoke(files);
            }
            var dirs = Directory.GetDirectories(path);
            foreach (var dir in dirs)
            {
                FindFiles(dir, action);
            }
        }
        /// <summary>
        /// 忽略的文件格式
        /// </summary>
        //static readonly string[] ignoreFiles = { ".meta", ".gitkeep", ".spriteatlas", ".DS_Store", ".cs", ".pdb" };
        static readonly string ignoreFiles = "*.meta*.gitkeep*.spriteatlas*.DS_Store*.cs*.pdb";
        public static bool IsFileIgnore(string path)
        {
            //if (!File.Exists(path))
            //{
            //    return true;
            //}
            var ext = Path.GetExtension(path);
            return string.IsNullOrEmpty(ext) == false && ignoreFiles.Contains(ext, StringComparison.OrdinalIgnoreCase);
        }
        /// <summary>
        /// 获取文件所在文件夹的名字
        /// </summary>
        /// <param name="path"></param>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public static string GetDirectoryName(string path, bool fullName)
        {
            path = Path.GetDirectoryName(path)?.Replace("\\", "/");
            if (!fullName)
            {
                int idx = path?.LastIndexOf("/", StringComparison.Ordinal) ?? -1;
                if (idx != -1)
                {
                    path = path?.Substring(idx + 1);
                }
            }
            return path;
        }
        /// <summary>
        /// 全路径转相对路径
        /// (Assets/...)
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>
        public static string ToRelativePath(string fullPath)
        {
            int index = fullPath.IndexOf(PathDefine.AssetsRelative, StringComparison.Ordinal);
            if (index == 0)
            {
                return fullPath;
            }
            else if (index < 0)
            { //没有 "Assets/" 或者在开头
                index = fullPath.IndexOf(PathDefine.PackageRelative, StringComparison.Ordinal); //Packages里的资源以Packages/开头，全名为"Packages/{包名}/..."
                if (index == 0)
                {//Packages下资源的相对路径
                    return fullPath;
                }
                else if (index < 0)
                {
                    var packageRoot = PathDefine.PackageReality;
                    index = fullPath.IndexOf(packageRoot, StringComparison.Ordinal);
                    if (index >= 0)
                    {
                        //Packages下资源的全路径
                        var tempPath = fullPath.Substring(index + packageRoot.Length);
                        var index_0 = tempPath.IndexOf('@');
                        var index_1 = tempPath.IndexOf('/');
                        if (index_1 - index_0 > 0 && index_0 >= 0)
                        {//裁剪版本信息
                            var version = tempPath.Substring(index_0, index_1 - index_0);
                            tempPath = $"{PathDefine.PackageRelative}{tempPath.Replace(version, "")}";
                        }
                        return tempPath;
                    }
                    return fullPath;
                }
            }
            return fullPath.Substring(index);
        }

        /// <summary>
        /// 判断字符串是否是数字
        /// </summary>
        /// <param name="message"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool IsNumberic(string message, out int result)
        {
            System.Text.RegularExpressions.Regex rex =
                new System.Text.RegularExpressions.Regex(@"^\d+$");
            result = -1;

            if (rex.IsMatch(message))
            {
                result = int.Parse(message);
                return true;
            }
            else
                return false;
        }
        /// <summary>
        /// 检测指定路径是否是包含平台信息
        /// result 返回1表是当前平台，返回-1表示包含平台信息但不是当前平台，返回0表示没有包含平台信息 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="platformNames"></param>
        /// <returns></returns>
        public static int VerifyPlatformPath(string path, string[] platformNames = null)
        {
            if (platformNames == null)
            {
                platformNames = Enum.GetNames(typeof(PlatformType));
            }
            var current = PlatformUtil.ActivePlatform.ToString();
            var projectPath = Environment.CurrentDirectory.Replace("\\", "/");
            var startIndex = path.StartsWith(projectPath) ? projectPath.Length : 0;
            foreach (var name in platformNames)
            {
                var platformIndex = path.IndexOf(name, startIndex);
                if (platformIndex >= 0)
                {
                    if (name.Equals(current))
                    {
                        return 1;
                    }
                    return -1;
                }
            }
            return 0;
        }
        /// <summary>
        /// 可加载资源路径
        /// </summary>
        /// <param name="includeResources"></param>
        /// <returns></returns>
        public static string[] GetProductAssetsRoots(bool includeResources = false)
        {
            ICollection<string> roots = new HashSet<string>();
            if (Directory.Exists(PathDefine.ResAddressableRelative))
            {
                roots.Add(PathDefine.ResAddressableRelative);
            }
            if (includeResources && Directory.Exists(PathDefine.ResourcesRelative))
            {
                roots.Add(PathDefine.ResourcesRelative);
            }
            GetDirectories(PathDefine.I18nAssetsRelative, PathDefine.ResAddressableName, SearchOption.AllDirectories, ref roots);
            return roots.ToArray();
        }
        public static string[] GetI18nAssetsRoots()
        {
            ICollection<string> directories = new HashSet<string>();
            GetDirectories(PathDefine.I18nAssetsRelative, PathDefine.ResAddressableName, SearchOption.AllDirectories, ref directories);
            return directories.ToArray();
        }
        /// <summary>
        /// 获取图集文件夹
        /// 文件夹名字：Atlas
        /// </summary>
        /// <returns></returns>
        public static string[] GetAtlasRoots()
        {
            const string atlasDir = "Atlas";
            ICollection<string> directories = new HashSet<string>();
            GetDirectories(PathDefine.ResAddressableRelative, atlasDir, SearchOption.AllDirectories, ref directories);
            GetDirectories(PathDefine.ResStaticRelative, atlasDir, SearchOption.AllDirectories, ref directories);
            GetDirectories(PathDefine.I18nAssetsRelative, atlasDir, SearchOption.AllDirectories, ref directories);
            return directories.ToArray();
        }
        private static void GetDirectories(string path, string searchPattern, SearchOption searchOption, ref ICollection<string> directories)
        {
            if (Directory.Exists(path))
            {
                var result = Directory.GetDirectories(path, searchPattern, searchOption);
                foreach (var directory in result)
                {
                    directories.Add(directory.Replace("\\", "/"));
                }
            }
        }
        public static bool HasChinese(string str)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(str, @"[\u4e00-\u9fa5]");
        }
        //[UnityEditor.MenuItem("Tools/Test/GenManifestBundleId")]
        //public static void GenManifestBundleId()
        //{
        //    var str = $"ProductAssetManifest.asset_AssetBundleManifest.asset_AssetReferenceManifest.asset";
        //    var bundleId = Crc32.GetCrc32(str);
        //    Debug.Log($"GenManifestBundleId:{bundleId}");
        //}
    }
}
