using System;
using System.IO;
using System.Text;

using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Lzw;

using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;

// https://github.com/icsharpcode/SharpZipLib
// https://icsharpcode.github.io/SharpZipLib/help/api/index.html
// https://icsharpcode.github.io/SharpZipLib/help/api/ICSharpCode.SharpZipLib.Lzw.LzwInputStream.html

// https://github.com/adamhathcock/sharpcompress
// https://github.com/adamhathcock/sharpcompress/blob/master/USAGE.md


namespace TopNugetPackages
{
    public class MainSharpZipLibDriver
    {
        private string ZFileName = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\Test1.txt.Z";
        private string Z7FileName = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\Test1.7z";
        private string ZipFileName = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\Test1.zip";
        private string OutFileName = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\Test1.txt";

        // Create Zip on entire folder
        private void Compress()
        {
            using (var archive = ZipArchive.Create())
            {
                archive.AddAllFromDirectory(@"D:\temp");
                archive.SaveTo(@"D:\dtemp.zip", CompressionType.Deflate);
            }
        }

        // uses LZW algorithm to decompress
        private void LZW_Decompress()
        {
            if (!File.Exists(ZFileName))
                return;

            using (Stream inStream = new LzwInputStream(File.OpenRead(ZFileName)))
            {
                long length = new FileInfo(ZFileName).Length;

                byte[] buffer = new byte[length * 10];    // Approximate enough size
                int read = inStream.Read(buffer, 0, buffer.Length);

                using (FileStream fs = File.Create(OutFileName, read))
                {
                    fs.Write(buffer, 0, read);
                }
            }            
        }

        // Can auto detect which compressing and decompress to file
        // Have limited compression format supported
        private void Zip_Decompress()
        {
            if (!File.Exists(ZipFileName))
                return;

            using (Stream stream = File.OpenRead(ZipFileName))
            using (var reader = ReaderFactory.Open(stream))
            {
                while (reader.MoveToNextEntry())
                {
                    if (!reader.Entry.IsDirectory)
                    {
                        Console.WriteLine(reader.Entry.Key);
                        reader.WriteEntryToDirectory(@"C:\temp", new ExtractionOptions()
                        {
                            ExtractFullPath = true,
                            Overwrite = true
                        });
                    }
                }
            }
        }

        // Main driver to compress/uncompress files
        public void DoIt()
        {
            Compress();
            LZW_Decompress();
            Zip_Decompress();
        }
    }
}