#include <algorithm>
#include <string>
#include <cstring>
#include <brotli/encode.h>
#include <httppp/http.h>

#pragma once

inline void compress(const std::string& in, std::string& out) {
    size_t compressed_size = BrotliEncoderMaxCompressedSize(in.length());

    unsigned char *buf = new unsigned char[compressed_size];

    size_t actual_compressed_len = compressed_size;

    BROTLI_BOOL result = BrotliEncoderCompress(
        BROTLI_DEFAULT_QUALITY,
        BROTLI_DEFAULT_WINDOW,
        BROTLI_MODE_TEXT,
        in.length(),
        (const unsigned char*)in.c_str(),
        &actual_compressed_len, //
        buf
    );

    if (result != BROTLI_TRUE) {
        out.clear();
        delete[] buf;
        return;
    }

    out.resize(actual_compressed_len);

    std::memcpy(out.data(), buf, actual_compressed_len);

    delete[] buf;
}

inline void sendCompressed(libhttppp::HttpRequest &req, libhttppp::HttpResponse &resp,
                           const char *body, size_t bodylen) {
    bool accept_br = false;
    libhttppp::HttpHeader::HeaderData *acph = req.getHeaderData("accept-encoding");
    if (acph) {
        for (auto *cdat = acph->getfirstValue(); cdat; cdat = cdat->nextvalue()) {
            std::string val = cdat->getvalue();
            std::transform(val.begin(), val.end(), val.begin(),
                [](unsigned char c) { return std::tolower(c); });
            if (val.find("br") != std::string::npos) {
                accept_br = true;
                break;
            }
        }
    }

    if (accept_br && bodylen > 0) {
        std::string in(body, bodylen);
        std::string compressed;
        compress(in, compressed);
        if (!compressed.empty()) {
            resp.setHeaderData("content-encoding")->push_back("br");
            resp.send(req, reinterpret_cast<const unsigned char*>(compressed.data()),
                      static_cast<int>(compressed.length()));
            return;
        }
    }

    resp.send(req, body, bodylen);
}
