#ifndef UASM_ZSTD_CODEC_H_
#define UASM_ZSTD_CODEC_H_

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace uasm::zstd
{
    constexpr size_t kDefaultMaxDecompressedSize = 512U * 1024U * 1024U;

    enum class ErrorKind
    {
        kNone,
        kInvalidArgument,
        kRange,
        kRuntime,
    };

    struct Result
    {
        std::vector<uint8_t> bytes;
        ErrorKind errorKind = ErrorKind::kNone;
        std::string errorMessage;

        explicit operator bool() const
        {
            return errorKind == ErrorKind::kNone;
        }
    };

    class Compressor
    {
    public:
        explicit Compressor(int level, int workers = 0);
        ~Compressor();

        Compressor(const Compressor &) = delete;
        Compressor &operator=(const Compressor &) = delete;

        const Result &status() const;
        Result Update(const uint8_t *data, size_t size);
        Result Finish();

    private:
        class Impl;
        std::unique_ptr<Impl> impl_;
    };

    class Decompressor
    {
    public:
        explicit Decompressor(size_t maxOutputSize);
        ~Decompressor();

        Decompressor(const Decompressor &) = delete;
        Decompressor &operator=(const Decompressor &) = delete;

        const Result &status() const;
        Result Update(const uint8_t *data, size_t size);
        Result Finish();

    private:
        class Impl;
        std::unique_ptr<Impl> impl_;
    };

    Result Compress(const uint8_t *data, size_t size, int level, int workers = 0);
    Result Decompress(const uint8_t *data, size_t size, size_t maxOutputSize);
} // namespace uasm::zstd

#endif // UASM_ZSTD_CODEC_H_