// 7Zip helper code by Peter Bromberg
// http://www.eggheadcafe.com/tutorials/aspnet/064b41e4-60bc-4d35-9136-368603bcc27a/7zip-lzma-inmemory-com.aspx

using System;
using System.IO;
using Windows.Storage.Streams;
using System.Collections.Generic;

namespace WinRT.BxlComponent.SevenZip.Compression.LZMA
{
    public static class SevenZipHelper
    {

       static int dictionary = 1 << 23;

      // static Int32 posStateBits = 2;
     // static  Int32 litContextBits = 3; // for normal files
        // UInt32 litContextBits = 0; // for 32-bit data
     // static  Int32 litPosBits = 0;
        // UInt32 litPosBits = 2; // for 32-bit data
    // static   Int32 algorithm = 2;
    // static    Int32 numFastBytes = 128;

     static   bool eos = false;





     static   CoderPropID[] propIDs = 
				{
					CoderPropID.DictionarySize,
					CoderPropID.PosStateBits,
					CoderPropID.LitContextBits,
					CoderPropID.LitPosBits,
					CoderPropID.Algorithm,
					CoderPropID.NumFastBytes,
					CoderPropID.MatchFinder,
					CoderPropID.EndMarker
				};

        // these are the default properties, keeping it simple for now:
     static   object[] properties = 
				{
					(Int32)(dictionary),
					(Int32)(2),
					(Int32)(3),
					(Int32)(0),
					(Int32)(2),
					(Int32)(128),
					"bt4",
					eos
				};


        //public static byte[] Compress(byte[] inputBytes)
        public static byte[] Compress(IList<byte> listInputBytes)
        {
            List<byte> listInput = new List<byte>(listInputBytes);
            byte[] inputBytes = listInput.ToArray();

            MemoryStream inStream = new MemoryStream(inputBytes);
            MemoryStream outStream = new MemoryStream();
            SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
            encoder.SetCoderProperties(propIDs, properties);
            encoder.WriteCoderProperties(outStream.AsRandomAccessStream());
            long fileSize = inStream.Length;
            for (int i = 0; i < 8; i++)
                outStream.WriteByte((Byte)(fileSize >> (8 * i)));
            encoder.Code(inStream.AsRandomAccessStream(), outStream.AsRandomAccessStream(), -1, -1, null);
            return outStream.ToArray();
        }

        //public static byte[] Decompress(byte[] inputBytes)
        public static byte[] Decompress(IList<byte> listInputBytes)
        {
            List<byte> listInput = new List<byte>(listInputBytes);
            byte[] inputBytes = listInput.ToArray();

            MemoryStream newInStream = new MemoryStream(inputBytes);

            SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
            
            newInStream.Seek(0, 0);
            MemoryStream newOutStream = new MemoryStream();

            byte[] properties2 = new byte[5];
            if (newInStream.Read(properties2, 0, 5) != 5)
                throw (new Exception("input .lzma is too short"));
            long outSize = 0;
            for (int i = 0; i < 8; i++)
            {
                int v = newInStream.ReadByte();
                if (v < 0)
                    throw (new Exception("Can't Read 1"));
                outSize |= ((long)(byte)v) << (8 * i);
            }
            List<byte> listProper = new List<byte>(properties2);
            decoder.SetDecoderProperties(listProper);

            long compressedSize = newInStream.Length - newInStream.Position;
            IRandomAccessStream writeStream = newOutStream.AsRandomAccessStream();

            decoder.Code(newInStream.AsRandomAccessStream(), writeStream, compressedSize, outSize, null);
            //newOutStream = writeStream.AsStream();
            writeStream.AsStreamForRead().CopyTo(newOutStream);
            byte[] b = newOutStream.ToArray();
           

            return b;



        }


    }
}
