using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

// 데이터 압축/해제 관련
namespace SystemX.Common.Archive
{
    public static class XDataArchive
    {
        public static byte[] CompressDeflateByteToByte(byte[] ucData)
        {
            byte[] ucCompressedByte;
            using (MemoryStream ms = new MemoryStream())
            {
                using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress))
                {
                    ds.Write(ucData, 0, ucData.Length);
                }
                ucCompressedByte = ms.ToArray();
            }

            return ucCompressedByte;
        }
        public static byte[] CompressGZipByteToByte(byte[] ucData)
        {
            byte[] ucCompressedByte;
            using (MemoryStream ms = new MemoryStream())
            {
                using (GZipStream gs = new GZipStream(ms, CompressionMode.Compress))
                {
                    gs.Write(ucData, 0, ucData.Length);
                }
                ucCompressedByte = ms.ToArray();
            }

            return ucCompressedByte;
        }
        public static byte[] DecompressDeflateByteToByte(byte[] ucCompressedData)
        {
            byte[] ucDecompressedByte;

            MemoryStream resultStream = new MemoryStream();
            using (MemoryStream ms = new MemoryStream(ucCompressedData))
            {
                using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress))
                {
                    ds.CopyTo(resultStream);
                    ds.Close();

                    ucDecompressedByte = resultStream.ToArray();
                }
            }

            return ucDecompressedByte;
        }
        public static byte[] DecompressGZipByteToByte(byte[] ucCompressedData)
        {
            byte[] ucDecompressedByte;

            MemoryStream resultStream = new MemoryStream();
            using (MemoryStream ms = new MemoryStream(ucCompressedData))
            {
                using (GZipStream gs = new GZipStream(ms, CompressionMode.Decompress))
                {
                    gs.CopyTo(resultStream);
                    gs.Close();

                    ucDecompressedByte = resultStream.ToArray();
                }
            }

            return ucDecompressedByte;
        }
        public static byte[] CompressDatasetToByte(DataSet ds)
        {
            //1. 데이터셋 Serialize
            ds.RemotingFormat = SerializationFormat.Binary;
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, ds);
            byte[] inbyt = ms.ToArray();

            //2. 데이터 압축
            System.IO.MemoryStream objStream = new MemoryStream();
            System.IO.Compression.DeflateStream objZS = new System.IO.
            Compression.DeflateStream(objStream, System.IO.Compression.
            CompressionMode.Compress);
            objZS.Write(inbyt, 0, inbyt.Length);
            objZS.Flush();
            objZS.Close();

            //3. 데이터 리턴
            return objStream.ToArray();
        }
        public static DataSet DecompressByteToDataset(byte[] bytDs)
        {
            DataSet outDs = new DataSet();
            MemoryStream inMs = new MemoryStream(bytDs);
            inMs.Seek(0, 0); //스트림으로 가져오기

            //1. 압축객체 생성- 압축 풀기
            DeflateStream zipStream = new DeflateStream(inMs,
            CompressionMode.Decompress, true);
            byte[] outByt = ReadFullStreamToByte(zipStream);
            zipStream.Flush();
            zipStream.Close();
            MemoryStream outMs = new MemoryStream(outByt);
            outMs.Seek(0, 0); //2. 스트림으로 다시변환
            outDs.RemotingFormat = SerializationFormat.Binary;

            //3. 데이터셋으로 Deserialize
            BinaryFormatter bf = new BinaryFormatter();
            outDs = (DataSet)bf.Deserialize(outMs, null);

            return outDs;
        }
        private static byte[] ReadFullStreamToByte(Stream stream)
        {
            //스트림을 Byte 배열로 변환
            byte[] buffer = new byte[1000000];
            using (MemoryStream ms = new MemoryStream())
            {
                while (true)
                {
                    int read = stream.Read(buffer, 0, buffer.Length);

                    if (read <= 0)
                        return ms.ToArray();

                    ms.Write(buffer, 0, read);
                }
            }
        }
    }
}
