using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;

namespace NFine.Code
{
    public class GZip
    {
        /// <summary>
        /// 压缩
        /// </summary>
        /// <param name="text">文本</param>
        public static string Compress(string text)
        {
            if (text.IsEmpty())
                return string.Empty;
            byte[] buffer = Encoding.UTF8.GetBytes(text);
            return Convert.ToBase64String(Compress(buffer));
        }

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="text">文本</param>
        public static string Decompress(string text)
        {
            if (text.IsEmpty())
                return string.Empty;
            byte[] buffer = Convert.FromBase64String(text);
            using (var ms = new MemoryStream(buffer))
            {
                using (var zip = new GZipStream(ms, CompressionMode.Decompress))
                {
                    using (var reader = new StreamReader(zip))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
        }

        /// <summary>
        /// 压缩
        /// </summary>
        /// <param name="buffer">字节流</param>
        public static byte[] Compress(byte[] buffer)
        {
            if (buffer == null)
                return null;
            using (var ms = new MemoryStream())
            {
                using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
                {
                    zip.Write(buffer, 0, buffer.Length);
                }
                return ms.ToArray();
            }
        }

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="buffer">字节流</param>
        public static byte[] Decompress(byte[] buffer)
        {
            if (buffer == null)
                return null;
            return Decompress(new MemoryStream(buffer));
        }

        /// <summary>
        /// 压缩
        /// </summary>
        /// <param name="stream">流</param>
        public static byte[] Compress(Stream stream)
        {
            if (stream == null || stream.Length == 0)
                return null;
            return Compress(StreamToBytes(stream));
        }

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="stream">流</param>
        public static byte[] Decompress(Stream stream)
        {
            if (stream == null || stream.Length == 0)
                return null;
            using (var zip = new GZipStream(stream, CompressionMode.Decompress))
            {
                using (var reader = new StreamReader(zip))
                {
                    return Encoding.UTF8.GetBytes(reader.ReadToEnd());
                }
            }
        }
        /// <summary>
        /// 流转换为字节流
        /// </summary>
        /// <param name="stream">流</param>
        public static byte[] StreamToBytes(Stream stream)
        {
            stream.Seek(0, SeekOrigin.Begin);
            var buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            return buffer;
        }

        /// <summary>
        /// 多文件压缩
        /// </summary>
        public static void ZipFileMainURL(string[] filenames, string[] filename, string name, int Level)
        {

            using (FileStream ZipFile = File.Create(name))
            {
                using (ZipOutputStream ZipStream = new ZipOutputStream(ZipFile))
                {
                    int n = 0;
                    foreach (string fileToZip in filenames)
                    {
                        string fileName = filename[n].ToString();

                        var url = fileToZip;


                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                        HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                        Stream responseStream = response.GetResponseStream();
                        ZipEntry ZipEntry = new ZipEntry(fileName);
                        ZipStream.PutNextEntry(ZipEntry);
                        ZipStream.SetLevel(Level);
                        var ms = new MemoryStream();
                        responseStream.CopyTo(ms);
                        byte[] bytes = ms.ToArray();
                        ZipStream.Write(bytes, 0, bytes.Length);


                        n++;
                        responseStream.Close();

                    }
                }

            }

        }

        /// <summary>
        /// 多文件压缩
        /// </summary>
        public static void ZipFileMain(string[] filenames, string[] filename, string name, int Level)
        {
            //ZipOutputStream s = new ZipOutputStream(File.Create(name));
            //Crc32 crc = new Crc32();
            ////压缩级别
            //s.SetLevel(Level);// 0 - store only to 9 - means best compression
            //try
            //{
            //    int m = 0;
            //    foreach (string file in filenames)
            //    {
            //        //打开压缩文件
            //        FileStream fs = File.OpenRead(file);//文件地址
            //        byte[] buffer = new byte[fs.Length];
            //        fs.Read(buffer, 0, buffer.Length);
            //        //建立压缩实体
            //        ZipEntry entity = new ZipEntry(filename[m].ToString());//源文件名
            //        //时间
            //        entity.DateTime = DateTime.Now;
            //        //控件大小
            //        entity.Size = fs.Length;
            //        fs.Close();
            //        crc.Reset();
            //        crc.Update(buffer);
            //        entity.Crc = crc.Value;
            //        s.PutNextEntry(entity);
            //        s.Write(buffer, 0, buffer.Length);
            //        m++;
            //    }
            //}
            //catch (Exception)
            //{
            //    throw;
            //}
            //finally
            //{
            //    s.Finish();
            //    s.Close();
            //}




            //生成的压缩文件为test.zip
            using (FileStream fsOut = File.Create(name))
            {
                //ZipOutputStream类的构造函数需要一个流,文件流、内存流都可以,压缩后的内容会写入到这个流中。
                using (ZipOutputStream zipStream = new ZipOutputStream(fsOut))
                {
                    int i = 0;
                    foreach (string item in filenames)
                    {
                        string fileName = item;
                        FileInfo fi = new FileInfo(fileName);
                        //entryName就是压缩包中文件的名称。
                        string entryName = filename[i];
                        //ZipEntry类代表了一个压缩包中的一个项,可以是一个文件,也可以是一个目录。
                        ZipEntry newEntry = new ZipEntry(entryName);
                        newEntry.DateTime = fi.LastWriteTime;
                        newEntry.Size = fi.Length;
                        //把压缩项的信息添加到ZipOutputStream中。
                        zipStream.PutNextEntry(newEntry);
                        byte[] buffer = new byte[4096];
                        //把需要压缩文件以文件流的方式复制到ZipOutputStream中。
                        using (FileStream streamReader = File.OpenRead(fileName))
                        {
                            StreamUtils.Copy(streamReader, zipStream, buffer);
                        }
                        zipStream.CloseEntry();
                        i++;
                    }
                    //使用流操作时一定要设置IsStreamOwner为false。否则很容易发生在文件流关闭后的异常。
                    zipStream.IsStreamOwner = false;
                    zipStream.Finish();
                    zipStream.Close();
                }

            }
        }
    }
}