using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SevenZip
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    public sealed class SevenZipUtil
    {
        /// <summary>			
        /// 压缩单文件夹中指定类型的文件		
        /// </summary>			
        /// <param name="sourceFolder">源文件目录</param>			
        /// <param name="outZipFile">要输出的压缩文件</param>	
        /// <param name="filter">文件类型(*.txt等)</param>
        /// <param name="delSrcFiles">压缩完后是否删除原文件</param>
        public static void ZipLargeFiles(string sourceFolder, string outZipFile, string filter = "*", bool delSrcFiles = true)
        {
            string cmdFormat;
            if (delSrcFiles)
                cmdFormat = "{0} a {1} {2} -sdel";
            else
                cmdFormat = "{0} a {1} {2}";
            ZipUsing7zip(cmdFormat, sourceFolder, outZipFile, new string[] { filter });
            if (delSrcFiles)
            {
                var files = Directory.GetFiles(sourceFolder);
                foreach (var file in files)
                {
                    if (file.ToUpper().EndsWith(filter.Replace("*", "").ToUpper()))
                    {
                        File.Delete(file);
                    }
                }

            }

        }

        /// <summary>			
        /// 压缩单文件夹中指定类型的文件		
        /// </summary>			
        /// <param name="sourceFolder">源文件目录</param>			
        /// <param name="outZipFile">要输出的压缩文件</param>	
        /// <param name="filter">文件类型(*.txt等)</param>
        /// <param name="delSrcFiles">压缩完后是否删除原文件</param>
        public static void ZipLargeFiles(string sourceFolder, string outZipFile, string[] filters, bool delSrcFiles = true)
        {
            string cmdFormat;
            if (delSrcFiles)
                cmdFormat = "a {0} {1} -sdel";
            else
                cmdFormat = "a {0} {1}";
            ZipUsing7zip(cmdFormat, sourceFolder, outZipFile, filters);
            if (delSrcFiles)
            {
                var files = Directory.GetFiles(sourceFolder);
                foreach (var file in files)
                {
                    if (EndsWith(file, filters))
                    {
                        File.Delete(file);
                    }
                }

            }
        }

        /// <summary>
        /// 解压指定的文件到压缩文件所在目录(返回目录路径)
        /// </summary>
        /// <param name="file"></param>
        /// <exception cref="Exception"></exception>
        public static string UnZipFile(string file,string filter="*")
        {
            try
            {   
                string errorMsg = "";
                string outputMsg = "";
                string dir = Path.GetDirectoryName(file);
                bool cmdResult = ExecuteCmdCommand($"e {file} -o{dir} -y {filter}", ref errorMsg, ref outputMsg);
                if (!cmdResult)
                {
                    string exceptionMsg = $"解压文件{file}时发生错误";
                    if (!string.IsNullOrWhiteSpace(errorMsg)) exceptionMsg = string.Format("{0} [{1}]", exceptionMsg, errorMsg);
                    throw new Exception(exceptionMsg);
                }
                return dir;
            }
            catch (Exception ex)
            {
                throw new Exception($"解压文件{file}时发生错误", ex);
            }
        }

        #region private
        private static bool ExecuteCmdCommand(string commandLine, ref string errorMsg, ref string outputMsg)
        {
            bool Flag = false;
            Process proc = new Process();
            try
            {
                // 配置CMD窗口的启动信息
                proc.StartInfo.FileName = "7z";
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.Arguments = commandLine;
                proc.StartInfo.RedirectStandardOutput = true;    // 开启重定向输出
                proc.StartInfo.RedirectStandardError = true;// 开启重定向错误输出
                proc.StartInfo.CreateNoWindow = true;
                // 不创建窗口
                proc.Start();
                proc.WaitForExit();
                errorMsg = proc.StandardError.ReadToEnd();
                outputMsg = proc.StandardOutput.ReadToEnd();
                if (string.IsNullOrWhiteSpace(errorMsg))
                    Flag = true;
                else
                    Flag = false;


            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                Flag = false;
            }
            finally
            {
                proc.Close();
                proc.Dispose();
            }
            return Flag;
        }
        private static bool EndsWith(string txt, string[] filters)
        {
            foreach (var filter in filters)
            {
                if (txt.ToUpper().EndsWith(filter.Replace("*", "").ToUpper()))
                    return true;
            }
            return false;

        }
        private static void ZipUsing7zip(string cmdFormat, string sourceFolder, string outZipFile, string[] filters)
        {
            try
            {
                // 获取要压缩的文件
                string filesPath = string.Join(" ", filters.Select(p => Path.Combine(sourceFolder, p)));

                // 格式化命令
                string cmd = string.Format(cmdFormat, outZipFile, filesPath);

                // 调用 7-Zip 执行命令
                string errorMsg = "";
                string outputMsg = "";
                bool cmdResult = ExecuteCmdCommand(cmd, ref errorMsg, ref outputMsg);
                if (!cmdResult)
                {
                    string exceptionMsg = "压缩文件时发生错误";
                    if (!string.IsNullOrWhiteSpace(errorMsg)) exceptionMsg = string.Format("{0} [{1}]", exceptionMsg, errorMsg);
                    throw new Exception(exceptionMsg);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("压缩文件时发生错误", ex);
            }
        }
        #endregion
    }
}
