using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace MWS.Library.Common.Helper
{
    public class FileHelper
    {
        public static string FileToString(string filePath)
        {
            return FileToString(filePath, Encoding.UTF8);
        }

        public static string FileToString(string filePath, Encoding encoding)
        {
            string result;
            if (!File.Exists(filePath))
            {
                result = string.Empty;
            }
            else
            {
                try
                {
                    using (StreamReader streamReader = new StreamReader(filePath, encoding))
                    {
                        result = streamReader.ReadToEnd();
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            return result;
        }

        public static FileStream FileToStream(string path)
        {
            Guard.ArgumentNotNullOrEmpty(path, "path");
            return new FileStream(path, FileMode.Open, FileAccess.Read);
        }

        public static byte[] FileToBytes(string filePath, int len = 0, int start = 0)
        {
            byte[] result;
            using (FileStream fileStream = FileToStream(filePath))
            {
                int num = (fileStream.Length > 2147483647L) ? int.MaxValue : ((int)fileStream.Length);
                int num2 = (len == 0) ? num : len;
                num2 = ((num2 >= num) ? num : num2);
                byte[] array = new byte[num2];
                fileStream.Read(array, start, num2);
                result = array;
            }
            return result;
        }

        public static void CreateDirectory(string directoryPath)
        {
            if (!string.IsNullOrEmpty(directoryPath))
            {
                if (!Directory.Exists(directoryPath))
                {
                    Executer.TryRunLogExceptioin(delegate
                    {
                        Directory.CreateDirectory(directoryPath);
                    }, string.Format("文件夹{0}创建失败", directoryPath));
                }
            }
        }

        public static string CreateFileDirectory(string filePath)
        {
            string filePath2 = GetFilePath(filePath, '\\');
            CreateDirectory(filePath2);
            return filePath2;
        }

        public static void CreateFile(string filePath)
        {
            if (!string.IsNullOrEmpty(filePath))
            {
                try
                {
                    if (!File.Exists(filePath))
                    {
                        string filePath2 = GetFilePath(filePath, '\\');
                        CreateDirectory(filePath2);
                        lock (_sync)
                        {
                            using (new FileStream(filePath, FileMode.OpenOrCreate))
                            {
                            }
                        }
                    }
                }
                catch (Exception innerException)
                {
                    throw new Exception("创建文件异常", innerException);
                }
            }
        }

        public static string CreateFile(string filePath, byte[] buffer)
        {
            if (!string.IsNullOrEmpty(filePath))
            {
                filePath = GetFileSavaPath(filePath);
                try
                {
                    FileInfo fileInfo = new FileInfo(filePath);
                    using (FileStream fileStream = fileInfo.Create())
                    {
                        fileStream.Write(buffer, 0, buffer.Length);
                    }
                    return filePath;
                }
                catch
                {

                }
            }
            return null;

        }

        public static void CreateFile(string filePath, string text)
        {
            CreateFile(filePath, text, Encoding.GetEncoding("utf-8"));
        }

        public static void CreateFile(string filePath, string text, Encoding encoding)
        {
            if (filePath != null && !(filePath == string.Empty))
            {
                string filePath2 = GetFilePath(filePath, '\\');
                if (!Directory.Exists(filePath2))
                {
                    Directory.CreateDirectory(filePath2);
                }
                FileInfo fileInfo = new FileInfo(filePath);
                using (FileStream fileStream = fileInfo.Create())
                {
                    using (StreamWriter streamWriter = new StreamWriter(fileStream, encoding))
                    {
                        streamWriter.Write(text);
                        streamWriter.Flush();
                    }
                }
            }
        }

        public static void Open(params string[] path)
        {
            if (!path.IsInvalid<string>())
            {
                string text = FileHelper.ConnectPath(path);
                try
                {
                    Process.Start("explorer.exe", text);
                }
                catch (Exception innerException)
                {
                    throw new Exception("打开文件出现异常:" + text, innerException);
                }
            }
        }

        public static void DeleteFile(string filePath)
        {
            if (!filePath.IsInvalid())
            {
                try
                {
                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }

                }
                catch (Exception innerException)
                {
                    throw new Exception("删除文件异常:" + filePath, innerException);
                }
            }
        }

        public static string GetFileName(string source, char separate = '\\')
        {
            string result;
            if (source.IsInvalid())
            {
                result = string.Empty;
            }
            else
            {
                source = source.TrimEnd(new char[]
                {
                    separate
                });
                int num = source.LastIndexOf(separate);
                if (num > 0)
                {
                    result = source.Substring(num + 1, source.Length - num - 1);
                }
                else
                {
                    result = source;
                }
            }
            return result;
        }

        public static string GetFilePath(string source, char separate = '\\')
        {
            string result;
            if (source.IsInvalid())
            {
                result = string.Empty;
            }
            else
            {
                source = source.TrimEnd(new char[]
                {
                    separate
                });
                int num = source.LastIndexOf(separate);
                if (num > 0)
                {
                    result = source.Substring(0, num + 1);
                }
                else
                {
                    result = source;
                }
            }
            return result;
        }

        public static string ConnectPath(char separate, params string[] path)
        {
            string result;
            if (path.IsInvalid<string>())
            {
                result = string.Empty;
            }
            else if (path.Length == 2)
            {
                result = string.Format("{0}{1}{2}", path[0].TrimEnd(new char[]
                {
                    separate
                }), separate, path[1].TrimStart(new char[]
                {
                    separate
                }));
            }
            else if (path.Length == 1)
            {
                result = path[0];
            }
            else
            {
                StringBuilder stringBuilder = new StringBuilder(32);
                foreach (string text in path)
                {
                    stringBuilder.Append(text.TrimEnd(new char[]
                    {
                        separate
                    }).TrimStart(new char[]
                    {
                        separate
                    })).Append(separate);
                }
                result = stringBuilder.ToString().TrimEnd(new char[]
                {
                    separate
                });
            }
            return result;
        }

        public static string ConnectPath(params string[] path)
        {
            return ConnectPath('\\', path);
        }

        public static string ConvertLinuxPath(string linuxpath, char validChar = '_')
        {
            int num = linuxpath.IndexOfAny(InvalidPathChars);
            string result;
            if (num >= 0)
            {
                result = ConvertLinuxPath(linuxpath.Replace(linuxpath[num], validChar), '_');
            }
            else
            {
                result = linuxpath.Replace('/', '\\');
            }
            return result;
        }

        public static string ConnectLinuxPath(string path1, string path2)
        {
            return ConnectPath('/', new string[]
            {
                path1,
                path2
            });
        }

        public static string GetLinuxFileName(string source)
        {
            return GetFileName(source, '/');
        }

        public static string GetLinuxFilePath(string source)
        {
            return GetFilePath(source, '/');
        }

        public static string GetExtension(string filePath)
        {
            Guard.ArgumentNotNullOrEmpty(filePath, "filePath");
            string result = string.Empty;
            try
            {
                result = Path.GetExtension(filePath).Replace(".", string.Empty);
            }
            catch (Exception)
            {
            }
            return result;
        }

        public static string TryGetExtension(string filename, char splitChar)
        {
            Guard.ArgumentNotNullOrEmpty(filename, "filePath");
            string[] source = filename.Split(new char[]
            {
                splitChar
            });
            string result = string.Empty;
            if (source.Any())
            {
                result = source.Last();
            }
            return result;
        }

        public static string GetPhysicalPath(string relativePath)
        {
            string result;
            if (string.IsNullOrEmpty(relativePath))
            {
                result = string.Empty;
            }
            else
            {
                relativePath = relativePath.Replace("/", "\\").Replace("~", string.Empty).Replace("~/", string.Empty);
                relativePath = (relativePath.StartsWith("\\") ? relativePath.Substring(1, relativePath.Length - 1) : relativePath);
                string applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
                string text = Path.Combine(applicationBase, relativePath);
                result = text;
            }
            return result;
        }

        public static string GetFileSize(string filePath)
        {
            Guard.ArgumentNotNullOrEmpty(filePath, "filePath");
            string result;
            if (!File.Exists(filePath))
            {
                result = string.Empty;
            }
            else
            {
                FileInfo fileInfo = new FileInfo(filePath);
                result = GetFileSize(fileInfo.Length, "F2");
            }
            return result;
        }

        public static long GetFileLength(string filepath)
        {
            long result = 0L;
            using (FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                result = fileStream.Length;
            }
            return result;
        }

        public static string GetFileSize(long len, string format = "F2")
        {
            string result;
            if (len <= 0L)
            {
                result = "0 KB";
            }
            else
            {
                string str = " B";
                double num = len;
                double num2 = 1024.0;
                if (len >= num2)
                {
                    num = len / num2;
                    str = " KB";
                }
                if (num > num2)
                {
                    num /= num2;
                    str = " MB";
                }
                if (num > num2)
                {
                    num /= num2;
                    str = " GB";
                }
                if (num - Math.Truncate(num) == 0.0)
                {
                    result = num.ToString("F2") + str;
                }
                else
                {
                    result = num.ToString("F2") + str;
                }
            }
            return result;
        }

        public static string GetFileSize(int len)
        {
            return GetFileSize(len, "F2");
        }

        public static IList<FileInfo> GetFiles(string folder, string extension)
        {
            return GetFiles(folder, new string[]
            {
                extension
            });
        }


        public static string GetFileSavaPath(string fileName)
        {
            string directory = Path.GetDirectoryName(fileName);   //文件所在路径
            string filename = Path.GetFileNameWithoutExtension(fileName);  //文件名
            string extension = Path.GetExtension(fileName);    //文件后缀 带点（.）
            int counter = 1;
            string newFilename = string.Format("{0}{1}", filename, extension); //文件名+后缀
            string newFullPath = Path.Combine(directory, newFilename);
            while (File.Exists(newFullPath)) //如果文件存在，如果存在count+1,继续循环
            {
                newFilename = string.Format("{0}({1}){2}", filename, counter, extension); //文件名+(count)+后缀
                newFullPath = Path.Combine(directory, newFilename);  //保存路径
                counter++; //count+1
            }
            return newFullPath;
        }


        public static IList<FileInfo> GetFiles(string folder, string[] extensions)
        {
            string[] files = Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories);
            return (from file in files
                    let extension = Path.GetExtension(file)
                    where extension != null && extensions.Contains(extension.ToLower())
                    select new FileInfo(file)).ToList();
        }

        public static bool IsValid(string file)
        {
            bool result;
            if (file.IsInvalid())
            {
                result = false;
            }
            else if (!File.Exists(file))
            {
                result = false;
            }
            else
            {
                FileInfo fileInfo = new FileInfo(file);
                result = (fileInfo.Length > 0L);
            }
            return result;
        }

        public static bool IsValidDictory(string path)
        {
            return !path.IsInvalid() && Directory.Exists(path);
        }

        public static byte[] ReadFileHead(string filePath, int index = 4)
        {
            byte[] result;
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                byte[] array = new byte[index];
                fileStream.Read(array, 0, index);
                result = array;
            }
            return result;
        }

        public static string FilterInvalidFileName(string oriName)
        {
            return _InvalidChars.Aggregate(oriName, (string current, char invalidChar) => current.Replace(invalidChar.ToString(), string.Empty));
        }

        public static bool IsFileInUsing(string path)
        {
            bool result = true;
            try
            {
                using (new FileStream(path, FileMode.Open))
                {
                    result = false;
                }
            }
            catch
            {
            }
            return result;
        }

        public static bool InputPathIsValid(string path)
        {
            return IsPositiveNumber(path) && IsHasUninvalidPathChars(path);
        }
        private static bool IsPositiveNumber(string path)
        {
            return Regex.IsMatch(path, "^[a-zA-Z]:\\\\[^\\/\\:\\*\\?\\\"\\<\\>\\|\\,]+$", RegexOptions.IgnoreCase);
        }

        private static bool IsHasUninvalidPathChars(string path)
        {
            return !Path.GetInvalidPathChars().Any(new Func<char, bool>(path.Contains<char>));
        }

        private static readonly object _sync = new object();

        private static readonly char[] InvalidPathChars = new char[]
        {
            '"',
            '<',
            '>',
            '|',
            '\0',
            '\u0001',
            '\u0002',
            '\u0003',
            '\u0004',
            '\u0005',
            '\u0006',
            '\a',
            '\b',
            '\t',
            '\n',
            '\v',
            '\f',
            '\r',
            '\u000e',
            '\u000f',
            '\u0010',
            '\u0011',
            '\u0012',
            '\u0013',
            '\u0014',
            '\u0015',
            '\u0016',
            '\u0017',
            '\u0018',
            '\u0019',
            '\u001a',
            '\u001b',
            '\u001c',
            '\u001d',
            '\u001e',
            '\u001f',
            '*',
            '?',
            ':'
        };

        private static readonly char[] _InvalidChars = Path.GetInvalidFileNameChars();
    }
}
