using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
namespace GFGEditor
{
    public class FileUtil
    {
        public static bool CheckPathInParent(string path, string parent)
        {
            path = path.Replace('\\', '/');
            path = path + "/";
            parent = parent.Replace('\\', '/');
            parent = parent + "/";
            parent = Regex.Replace(parent, "//", "/");
            return path.Contains(parent);
        }
        /// 
        /// 
        /// 
        /// 
        /// ,路径比须从Asset起,例如"Assets/Res/Effect"
        /// 
        public static void ForeachFileInDir(string dirPath, List excludeDirs, Action action)
        {
            List excludeDirPaths = new List();
            if (excludeDirs != null)
            {
                foreach (var excDir in excludeDirs)
                {
                    var t = Environment.CurrentDirectory + "/" + excDir;
                    t = t.Replace('\\', '/');
                    excludeDirPaths.Add(t);
                }
            }
            var t1 = dirPath.Replace('\\', '/');
            if (Directory.Exists(dirPath) && !excludeDirPaths.Contains(t1))
            {
                var files = Directory.GetFiles(dirPath);
                var dirs = Directory.GetDirectories(dirPath);
                foreach (var file in files)
                {
                    action?.Invoke(file);
                }
                foreach (var dir in dirs)
                {
                    ForeachFileInDir(dir, excludeDirs, action);
                }
            }
        }
        public static void ForeachDirInDir(string dirPath, Action action)
        {
            if (Directory.Exists(dirPath))
            {
                var dirs = Directory.GetDirectories(dirPath);
                foreach (var dir in dirs)
                {
                    action?.Invoke(dir);
                }
            }
        }
        public static List CopyFilesTo(string sourcePath, string targetPath, string saveName, string[] includeExtensionNames = null, string regular = null)
        {
            List result = new List();
            if (Directory.Exists(sourcePath))
            {
                var files = Directory.GetFiles(sourcePath);
                var dirs = Directory.GetDirectories(sourcePath);
                foreach (var dir in dirs)
                {
                    List tempResult = CopyFilesTo(dir, targetPath, saveName, includeExtensionNames, regular);
                    result.AddRange(tempResult);
                }
                Dictionary sourceImageMD5 = new Dictionary();
                sourceImageMD5 = ImagesClip.ReadSourceImagesMD5(saveName);
                foreach (var file in files)
                {
                    var fileName = Path.GetFileName(file);
                    if (fileName.Trim() == fileName && CheckStringByRegular(fileName, regular))
                    {
                        string extensionName = Path.GetExtension(file);
                        if (includeExtensionNames == null || Array.IndexOf(includeExtensionNames, extensionName) >= 0)
                        {
                            if (!sourceImageMD5.ContainsKey(file) || sourceImageMD5[file] != FileUtil.md5file(file))
                            {
                                sourceImageMD5[file] = FileUtil.md5file(file);
                            }
                            string targetFilePath = targetPath + fileName;
                            if (!File.Exists(targetFilePath) || !Equals(file, targetFilePath))
                            {
                                File.Copy(file, targetFilePath, true);
                                result.Add(file);
                            }
                        }
                    }
                    else
                    {
                        Debug.LogError($"请检查文件名 {file}");
                    }
                }
                ImagesClip.WriteSourceImagesMD5(sourceImageMD5, saveName);
            }
            return result;
        }
        public static bool CheckStringByRegular(string str, string regular)
        {
            str = Path.GetFileNameWithoutExtension(str);
            if (regular == null)//不进行正则检测
            {
                return true;
            }
            if (System.Text.RegularExpressions.Regex.IsMatch(str, regular))
            {
                return true;
            }
            return false;
        }
        public static List CopyDirsAndFilesInSubDirTo(string sourcePath, string targetPath, string[] excludeExtensionNames = null, string regular = null)
        {
            List result = new List();
            if (Directory.Exists(sourcePath))
            {
                var dirs = Directory.GetDirectories(sourcePath);
                foreach (var dir in dirs)
                {
                    var dirName = Path.GetFileName(dir);
                    var currTargetPath = targetPath + dirName + "/";
                    if (!CheckStringByRegular(dirName, regular)) continue;
                    if (!Directory.Exists(currTargetPath))
                    {
                        Directory.CreateDirectory(currTargetPath);
                    }
                    List tempResult = CopyFilesAndDirsTo(dir, currTargetPath, excludeExtensionNames);
                    result.AddRange(tempResult);
                }
            }
            return result;
        }
        public static List CopyFilesAndDirsTo(string sourcePath, string targetPath, string[] excludeExtensionNames = null)
        {
            List result = new List();
            if (Directory.Exists(sourcePath))
            {
                var files = Directory.GetFiles(sourcePath);
                var dirs = Directory.GetDirectories(sourcePath);
                foreach (var file in files)
                {
                    var fileName = Path.GetFileName(file);
                    if (fileName.Trim() == fileName)
                    {
                        string extensionName = Path.GetExtension(file);
                        if (!FileNameContainsArrayElement(fileName, excludeExtensionNames))
                        {
                            string targetFilePath = targetPath + fileName;
                            if (!File.Exists(targetFilePath) || !Equals(file, targetFilePath))
                            {
                                File.Copy(file, targetFilePath, true);
                                result.Add(file);
                            }
                        }
                    }
                    else
                    {
                        Debug.LogError($"请检查文件名 {file}");
                    }
                }
                foreach (var dir in dirs)
                {
                    var dirName = Path.GetFileName(dir);
                    var currTargetPath = targetPath + dirName + "/";
                    if (!Directory.Exists(currTargetPath))
                    {
                        Directory.CreateDirectory(currTargetPath);
                    }
                    List tempResult = CopyFilesAndDirsTo(dir, currTargetPath, excludeExtensionNames);
                    result.AddRange(tempResult);
                }
            }
            return result;
        }
        public static string md5file(string file)
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
                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"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("md5file() fail, error:" + ex.Message);
            }
        }
        public static bool Equals(string fileA, string fileB)
        {
            return md5file(fileA) == md5file(fileB);
        }
        public static bool FileNameContainsArrayElement(string fileName, string[] excludeExtensionNames = null)
        {
            if (excludeExtensionNames != null)
            {
                foreach (var item in excludeExtensionNames)
                {
                    if (fileName.Contains(item))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        public static void DeleteUnnecessaryImage(string targetPath, string[] saveNames)
        {
            if (saveNames.Length > 0)
            {
                DeleteUnnecessaryImageMD5(saveNames);
                DeleteUnnecessaryImageRes(targetPath, saveNames);
            }
            if (targetPath == ImportArtResTool.DressUpTargetPath)
            {
                DeleteUnnecessaryImagePos(ImportArtResTool.DressUpTargetPath);
                // DeleteUnnecessaryImageMD5(ImportArtResTool.DressUpMd5FileSaveName);
            }
            Debug.Log(targetPath + "清除完成");
        }
        //清除无资源的Md5数据
        public static void DeleteUnnecessaryImageMD5(string[] saveNames)
        {
            for (int j = 0; j < saveNames.Length; j++)
            {
                string saveName = saveNames[j];
                List rKeys = new List();
                Dictionary sourceResMD5 = new Dictionary();
                sourceResMD5 = ImagesClip.ReadSourceImagesMD5(saveName);
                ICollection keys = sourceResMD5.Keys;
                foreach (string key in keys)
                {
                    if (!File.Exists(key))
                    {
                        rKeys.Add(key);
                    }
                }
                for (int i = 0; i < rKeys.Count; i++)
                {
                    sourceResMD5.Remove(rKeys[i]);
                }
                ImagesClip.WriteSourceImagesMD5(sourceResMD5, saveName);
            }
        }
        public static void DeleteUnnecessaryImageRes(string targetPath, string[] saveNames)
        {
            string[] includeExtensionNames = new string[] { ".png", ".jpg" };
            if (!Directory.Exists(targetPath))
            {
                Debug.Log(targetPath + "不存在!!!!!");
                return;
            }
            var files = Directory.GetFiles(targetPath);
            foreach (var file in files)//遍历项目中的所有资源
            {
                if (file.Trim() != file)
                {
                    Debug.LogError($"请检查文件名 {file}");
                    continue;
                }
                string fileName = Path.GetFileName(file);
                string extensionName = Path.GetExtension(file);
                if (extensionName == ".meta" || extensionName == ".bytes") continue;
                bool has = false;
                for (int i = 0; i < saveNames.Length; i++)
                {
                    string saveName = saveNames[i];
                    Dictionary sourceResMD5 = new Dictionary();
                    sourceResMD5 = ImagesClip.ReadSourceImagesMD5(saveName);
                    ICollection keys = sourceResMD5.Keys;
                    foreach (string key in keys)//遍历MD5中记录的所有正式资源路径
                    {
                        // if (!File.Exists(key))//记录的路径在正式资源里不存在
                        // {
                        string sourceName = Path.GetFileName(key);
                        if (sourceName == fileName)
                        {
                            has = true;
                            break;
                        }
                    }
                }
                if (!has) File.Delete(targetPath + fileName);
            }
            Debug.Log(targetPath + "清除完成!");
        }
        //清除冗余位置文件
        public static void DeleteUnnecessaryImagePos(string targetPath)
        {
            string[] includeExtensionNames = new string[] { ".png", ".jpg" };
            var files = Directory.GetFiles(targetPath);
            foreach (var file in files)
            {
                if (file.Trim() != file)
                {
                    Debug.LogError($"请检查文件名 {file}");
                    continue;
                }
                string extensionName = Path.GetExtension(file);
                string fileName = Path.GetFileName(file).Split('.')[0]; ;
                string targetFilePath = targetPath + fileName;
                if (extensionName == ".bytes" && !File.Exists(targetFilePath + includeExtensionNames[0]) && !File.Exists(targetFilePath + includeExtensionNames[1]))
                {
                    File.Delete(targetPath + Path.GetFileName(file));
                }
            }
            Debug.Log("位置文件清除完成!");
        }
        public static void DeleteUnnecessaryAnimation(string localDir, string sourceDirs)
        {
            if (Directory.Exists(localDir))
            {
                var localFiles = Directory.GetFiles(localDir);
                var localDirs = Directory.GetDirectories(localDir);
                var souFiles = Directory.GetFiles(sourceDirs);
                var souDirs = Directory.GetDirectories(sourceDirs);
                foreach (var lfile in localFiles)
                {
                    var lfileName = Path.GetFileName(lfile);
                    bool existFile = false;
                    foreach (var sfile in souFiles)
                    {
                        var sfileName = Path.GetFileName(sfile);
                        if (lfileName == sfileName)
                        {
                            existFile = true;
                            break;
                        }
                    }
                    if (!existFile)
                    {
                        File.Delete(lfile);
                    }
                }
                foreach (var lDir in localDirs)
                {
                    string lDirName = Path.GetFileName(lDir);
                    // if (lDirName == "Card") continue;
                    bool needDelete = false;
                    foreach (var sDir in souDirs)
                    {
                        string sDirName = Path.GetFileName(sDir);
                        if (lDirName == sDirName)
                        {
                            needDelete = true;
                            DeleteUnnecessaryAnimation(lDir, sDir);
                        }
                    }
                    if (!needDelete)
                    {
                        Directory.Delete(lDir, true);
                    }
                }
            }
        }
    }
}