/*---------------------------------------------------------------------------*/
/* zlib_stream.h                                                             */
/* copyright (c) innovaphone 2021                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

class UZLibStream
{
public:
    UZLibStream() {}
    virtual ~UZLibStream() {}

    virtual void ZLibStreamResult(class IZLibStream * stream, byte * buffer, size_t bufferSize, bool eos) = 0;
};


class IZLibStream
{
public:
    enum class State {
        OK,
        NEED_DATA,
        DONE,
        ERROR,
        STREAM_ERROR,
        MEMORY_ERROR,
        NO_DATA
    };

    enum class CompressionType {
        DECOMPRESSION,
        COMPRESSION_NONE,
        COMPRESSION_BEST_SPEED,
        COMPRESSION_MAX,
        COMPRESSION_DEFAULT
    };

    static IZLibStream * Create(CompressionType type, class UZLibStream * user);
    static class IZLibBuffer * Compress(byte * data, size_t dataLen, CompressionType type = CompressionType::COMPRESSION_DEFAULT);
    static class IZLibBuffer * Decompress(byte * compressedData, size_t compressedDataLen);
    static State Compress(byte * outBuffer, size_t outBufferSize, byte * data, size_t dataLen, size_t & outCompressedSize, CompressionType type = CompressionType::COMPRESSION_DEFAULT);
    static State Decompress(byte * outBuffer, size_t outBufferSize, byte * compressedData, size_t compressedDataLen, size_t & outDecompressedSize);

    IZLibStream() {}
    virtual ~IZLibStream() {}

    virtual State Init(CompressionType type) = 0;
    virtual State Process(byte * data, size_t size, bool isLastPart = false) = 0;
    virtual bool IsDecompressing() = 0;
    virtual ulong64 BytesRead() = 0;
    virtual ulong64 BytesWritten() = 0;

    static inline const char * StateToStr(State s)
    {
        switch (s)
        {
        case State::NEED_DATA: return "NEED_DATA";
        case State::NO_DATA: return "NO_DATA";
        case State::ERROR: return "ERROR";
        case State::STREAM_ERROR: return "STREAM_ERROR";
        case State::MEMORY_ERROR: return "MEMORY_ERROR";
        default: return "OK";
        }
    }
};


class IZLibBuffer {
public:
    IZLibBuffer() {}
    virtual ~IZLibBuffer() {}

    virtual IZLibStream::State Result() = 0;
    virtual const byte * Data() = 0;
    virtual size_t Size() = 0;
};
