using System.Collections.Generic;
using System.Text;

namespace Apewer.Internals
{

    internal class FileHelper
    {

        /// <summary>获取指定目录下子文件的路径,不递归子目录。</summary>
        /// <param name="argDirectory">顶级目录。</param>
        public static List<string> GetSubFilePath(string argDirectory)
        {
            return GetSubFilePath(argDirectory, false, false);
        }

        /// <summary>获取指定目录下子文件的路径。</summary>
        /// <param name="argDirectory">顶级目录。</param>
        /// <param name="argRecurSub">递归子目录。</param>
        /// <param name="argRecurPrecedence">优先排列递归项。</param>
        public static List<string> GetSubFilePath(string argDirectory, bool argRecurSub, bool argRecurPrecedence)
        {
            return GetSubFilePath(argDirectory, argRecurSub ? -1 : 0, argRecurPrecedence);
        }

        /// <summary>获取指定目录下子文件的路径。</summary>
        /// <param name="argDirectory">顶级目录。</param>
        /// <param name="argRecurDepth">子目录递归深度。</param>
        /// <param name="argRecurPrecedence">优先排列递归项。</param>
        public static List<string> GetSubFilePath(string argDirectory, int argRecurDepth, bool argRecurPrecedence)
        {
            var list = new List<string>();
            if (string.IsNullOrEmpty(argDirectory)) return list;

            var directorylist = new List<string>();
            if (argRecurDepth == 0)
            {
                directorylist.Add(argDirectory);
            }
            else
            {
                var recurdicrotylist = GetSubDirectoryPath(argDirectory, argRecurDepth, argRecurPrecedence);
                if (argRecurPrecedence)
                {
                    directorylist.AddRange(recurdicrotylist);
                    directorylist.Add(argDirectory);
                }
                else
                {
                    directorylist.Add(argDirectory);
                    directorylist.AddRange(recurdicrotylist);
                }
            }

            foreach (var directory in directorylist)
            {
                try
                {
                    var files = System.IO.Directory.GetFiles(directory);
                    list.AddRange(files);
                }
                catch { }
            }

            return list;
        }

        /// <summary>获取指定目录下子目录的路径,不递归子目录。</summary>
        /// <param name="argDirectory">顶级目录。</param>
        public static List<string> GetSubDirectoryPath(string argDirectory)
        {
            return GetSubDirectoryPath(argDirectory, false, false);
        }

        /// <summary>获取指定目录下子目录的路径。</summary>
        /// <param name="argDirectory">顶级目录。</param>
        /// <param name="argRecurSub">递归子目录。</param>
        /// <param name="argRecurPrecedence">优先排列递归项。</param>
        public static List<string> GetSubDirectoryPath(string argDirectory, bool argRecurSub, bool argRecurPrecedence)
        {
            return GetSubDirectoryPath(argDirectory, argRecurSub ? -1 : 0, argRecurPrecedence);
        }

        /// <summary>获取指定目录下子目录的路径。</summary>
        /// <param name="argDirectory">顶级目录。</param>
        /// <param name="argRecurDepth">子目录递归深度。</param>
        /// <param name="argRecurPrecedence">优先排列递归项。</param>
        public static List<string> GetSubDirectoryPath(string argDirectory, int argRecurDepth, bool argRecurPrecedence)
        {
            var list = new List<string>();
            if (string.IsNullOrEmpty(argDirectory)) return list;

            var directories = new string[0];

            try
            {
                directories = System.IO.Directory.GetDirectories(argDirectory);
            }
            catch { }

            foreach (var directory in directories)
            {
                var recurlist = new List<string>();
                if (argRecurDepth != 0)
                {
                    var depth = (argRecurDepth > 0) ? argRecurDepth - 1 : argRecurDepth;
                    var subrecur = GetSubDirectoryPath(directory, depth, argRecurPrecedence);
                    recurlist.AddRange(subrecur);
                }

                if (argRecurPrecedence)
                {
                    list.AddRange(recurlist);
                    list.Add(directory);
                }
                else
                {
                    list.Add(directory);
                    list.AddRange(recurlist);
                }
            }

            return list;
        }

        /// <summary>判断文件是否存在。</summary>
        /// <param name="argPath">文件路径。</param>
        public static bool Exist(string argPath)
        {
            if (string.IsNullOrEmpty(argPath)) return false;
            if (System.IO.File.Exists(argPath)) return true;
            if (System.IO.Directory.Exists(argPath)) return true;
            return false;
        }

        /// <summary>判断文件是否存在。</summary>
        /// <param name="argPath">文件路径。</param>
        public static bool Exists(string argPath)
        {
            return Exist(argPath);
        }

        /// <summary>获取文件流,并锁定文件。若文件不存在,则先创建文件;若获取失败,则返回 NULL 值。</summary>
        /// <param name="argPath">文件路径。</param>
        public static System.IO.Stream Open(string argPath)
        {
            return Open(argPath, false);
        }

        /// <summary>获取文件流。若文件不存在,则先创建文件;若获取失败,则返回 NULL 值。</summary>
        /// <param name="argPath">文件路径。</param>
        /// <param name="argShare">共享。</param>
        public static System.IO.Stream Open(string argPath, bool argShare)
        {
            try
            {
                if (!string.IsNullOrEmpty(argPath))
                {
                    var mode = System.IO.FileMode.OpenOrCreate;
                    var access = System.IO.FileAccess.ReadWrite;
                    var share = argShare ? System.IO.FileShare.ReadWrite : System.IO.FileShare.None;
                    var stream = new System.IO.FileStream(argPath, mode, access, share);
                    return stream;
                }
            }
            catch { }
            return null;
        }

        /// <summary>创建一个空文件且不保留句柄。</summary>
        /// <param name="argPath">文件路径,若已存在则返回失败。</param>
        /// <param name="argReplace">替换现有文件。</param>
        /// <returns>创建成功。</returns>
        public static bool Create(string argPath, bool argReplace = false)
        {
            try
            {
                if (string.IsNullOrEmpty(argPath)) return false;

                if (argReplace) { if (!Delete(argPath)) return false; }
                else { if (Exist(argPath)) return false; }

                if (!Exist(argPath))
                {
                    var pd = System.IO.Directory.GetParent(argPath).FullName;
                    System.IO.Directory.CreateDirectory(pd);
                    var bs = Constant.EmptyBytes;
                    Write(argPath, bs);
                    return true;
                }
            }
            catch { }
            return false;
        }

        /// <summary>向文件写入数据。文件不存在将创建,存在则覆盖。</summary>
        public static bool Write(string argPath, byte[] argData)
        {
            try { System.IO.File.WriteAllBytes(argPath, argData); return true; }
            catch { return false; }
        }

        /// <summary>向文件写入文本。文件不存在将创建,存在则覆盖。</summary>
        public static bool Write(string argPath, string argText)
        {
            try { System.IO.File.WriteAllText(argPath, argText); return true; }
            catch { return false; }
        }

        /// <summary>向文件写入文本。文件不存在将创建,存在则覆盖。</summary>
        public static bool Write(string argPath, string argText, Encoding argEncoding)
        {
            try { System.IO.File.WriteAllText(argPath, argText, argEncoding); return true; }
            catch { return false; }
        }

        /// <summary>向文件追加数据。文件不存在将创建,存在则覆盖。</summary>
        public static bool Append(string argPath, params byte[] argData)
        {
            var result = false;
            System.IO.FileStream file = null;
            try
            {
                file = new System.IO.FileStream(argPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite);
                file.Position = file.Length;
                //vfile.Seek(vfile.Length, SeekOrigin.End);
                file.Write(argData, 0, argData.Length);
                file.Flush();
                file.Close();
                result = true;
            }
            finally
            {
                if (file != null)
                {
                    file.Dispose();
                    file = null;
                }
            }
            return result;
        }

        /// <summary>读取文件中的数据。</summary>
        public static byte[] Read(string argPath)
        {
            try { if (Exist(argPath)) return System.IO.File.ReadAllBytes(argPath); } catch { }
            return Constant.EmptyBytes;
        }

        /// <summary>读取文件中的数据,可选择去除 BOM 字节。</summary>
        public static byte[] Read(string argPath, bool argWipeBom)
        {
            try
            {
                if (Exist(argPath))
                {
                    var bytes = System.IO.File.ReadAllBytes(argPath);
                    if (argWipeBom) bytes = ByteHelper.WipeTextBom(bytes);
                    return bytes;
                }
            }
            catch { }
            return Constant.EmptyBytes;
        }

        /// <summary>读取文件中的文本。</summary>
        public static string Read(string argPath, Encoding argEncoding)
        {
            try { if (Exist(argPath)) return System.IO.File.ReadAllText(argPath, argEncoding); } catch { }
            return Constant.EmptyString;
        }

        /// <summary>删除文件。</summary>
        /// <param name="argPath">文件路径,若不存在文件则返回成功。</param>
        /// <returns>删除成功。</returns>
        public static bool Delete(string argPath)
        {
            if (string.IsNullOrEmpty(argPath)) return false;
            if (!Exist(argPath)) return true;
            try
            {
                if (Exist(argPath)) System.IO.File.Delete(argPath);
                if (System.IO.Directory.Exists(argPath)) System.IO.Directory.Delete(argPath);
                return !Exist(argPath);
            }
            catch { return false; }
        }

        /// <summary>复制文件,如果新路径已存在则不复制且返回 False 值。</summary>
        public static bool Copy(string argOldPath, string argNewPath)
        {
            return Copy(argOldPath, argNewPath, false);
        }

        /// <summary>复制文件。</summary>
        /// <param name="argOldPath">旧路径。</param>
        /// <param name="argNewPath">新路径。</param>
        /// <param name="argReplace">新路劲存在时,替换新文件。</param>
        public static bool Copy(string argOldPath, string argNewPath, bool argReplace)
        {
            if (string.IsNullOrEmpty(argOldPath)) return false;
            if (string.IsNullOrEmpty(argNewPath)) return false;
            if (!Exist(argOldPath)) return false;
            try
            {
                System.IO.File.Copy(argOldPath, argNewPath, argReplace);
                return true;
            }
            catch { return false; }
        }



        /// <summary>确保目录存在,若不存在则创建,返回目录的存在状态。</summary>
        public static bool AssureDirectory(string argPath)
        {
            if (string.IsNullOrEmpty(argPath)) return false;
            try
            {
                if (System.IO.Directory.Exists(argPath)) return true;
                var cd = System.IO.Directory.CreateDirectory(argPath);
                return cd.Exists;
            }
            catch { return false; }
        }

    }

}