using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using JWH;
using JWH.DATA;

namespace DDUtilityApp.LOGPARSER.DATA
{

    public class CompressInformation : DataTableBase
    {

        public string ExtractPath { get; protected set; }

        public string FileName { get; protected set; }

        public List<FileInfo> Files { get; set; } = new List<FileInfo>();

        public CompressInformation()
        {
        }

        public  CompressInformation(string filename)
        {
            this.FileName = filename;
            this.Files.AddRange(this.Decompress(filename).ToArray());
        }

        private List<FileInfo> Decompress(string srcFile)
        {
            List<FileInfo> lstFile = new List<FileInfo>();
            try
            {

                string extension = System.IO.Path.GetExtension(srcFile);
                if (!Directory.Exists(GlobalVariable.Instance.WorkflowPath)) Directory.CreateDirectory(GlobalVariable.Instance.WorkflowPath);

                string destFile = $@"{GlobalVariable.Instance.WorkflowPath}{System.IO.Path.GetFileNameWithoutExtension(srcFile)}";
                if (this.Decompress(srcFile, destFile) == false) return lstFile;

                string directoryName = $@"{GlobalVariable.Instance.WorkflowPath}{System.IO.Path.GetFileNameWithoutExtension(srcFile)}_{DateTime.Now.ToString("MMddHHmmss")}";
                if (!Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName);
                this.ExtractPath = directoryName;

                FileInfo destFileInfo = new FileInfo(destFile);
                using (FileStream readStream = destFileInfo.OpenRead())
                {
                    while (true)
                    {
                        // Get Length of FileName
                        byte[] byteLength = new byte[4];
                        int nRead = readStream.Read(byteLength, 0, 4);
                        if (nRead <= 0) break;
                        int lenFilename = BitConverter.ToInt32(byteLength, 0);
                        lenFilename *= 2;

                        // Get FileName
                        byte[] byteFilename = new byte[lenFilename];
                        nRead = readStream.Read(byteFilename, 0, lenFilename);
                        if (nRead <= 0) break;
                        string filename = Encoding.Unicode.GetString(byteFilename);

                        // Get Length of File Body
                        nRead = readStream.Read(byteLength, 0, 4);
                        if (nRead <= 0) break;
                        int lenFile = BitConverter.ToInt32(byteLength, 0);

                        if (lenFile == -1)
                        {
                            continue;
                        }

                        // Get File Body
                        byte[] byteFileBody = new byte[lenFile];
                        nRead = readStream.Read(byteFileBody, 0, lenFile);
                        if (nRead <= 0) break;

                        // Write File
                        using (FileStream writeStream = File.Create($"{directoryName}\\{filename}"))
                            writeStream.Write(byteFileBody, 0, lenFile);

                        lstFile.Add(new FileInfo($"{directoryName}\\{filename}"));
                    }
                }
                destFileInfo.Delete();

                return lstFile;
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return lstFile;
            }
        }

        private void Compress(DirectoryInfo directorySelected)
        {
            foreach (FileInfo fileToCompress in directorySelected.GetFiles())
            {
                using (FileStream originalFileStream = fileToCompress.OpenRead())
                {
                    if ((File.GetAttributes(fileToCompress.FullName) &
                       FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
                    {
                        using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
                        {
                            using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
                            {
                                originalFileStream.CopyTo(compressionStream);
                            }
                        }
                        FileInfo info = new FileInfo(GlobalVariable.Instance.WorkflowPath + Path.DirectorySeparatorChar + fileToCompress.Name + ".gz");
                        Console.WriteLine($"Compressed {fileToCompress.Name} from {fileToCompress.Length.ToString()} to {info.Length.ToString()} bytes.");
                    }
                }
            }
        }

        private bool Decompress(string srcFile, string destFile)
        {
            try
            {
                FileInfo srcFileInfo = new FileInfo(srcFile);
                using (FileStream srcStream = srcFileInfo.OpenRead())
                {
                    using (FileStream destStream = File.Create(destFile))
                    {
                        using (GZipStream zipStream = new GZipStream(srcStream, CompressionMode.Decompress))
                        {
                            zipStream.CopyTo(destStream);
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return false;
            }
        }

    }

}
