#pragma once

#include "hpack_definitions.h"

#include <balancer/kernel/http2/server/common/http2_common.h>
#include <balancer/kernel/http/parser/http.h>
#include <balancer/kernel/memory/chunks.h>

#include <util/system/compiler.h>
#include <util/system/types.h>

namespace NSrvKernel::NHTTP2 {

    // The writer expects the whole header list to be known beforehand.
    class THPackWriter {
    public:
        explicit THPackWriter(const THPackEncoderSettings& settings) noexcept;

        TChunkList& GetChunkList() noexcept;

        void Commit() noexcept;

        void WriteHeaderName(TStringBuf name) noexcept;

        void WriteHeaderValue(TStringBuf value, bool allowHuffman) noexcept;

        void WriteTableSizeUpdate(ui32 newSize) noexcept;

        void WriteIndexedAll(ui32 index) noexcept;

        void WriteHeaderField(EHPackHeaderRule rule, ui32 nameIndex) noexcept;

    private:
        void EnsureBuffer(size_t needed) noexcept;

        void NextChunk(size_t nextSize) noexcept;

    private:
        enum EStringMode {
            SM_NAME, SM_VALUE, SM_VALUE_NO_HUFFMAN
        };

        void WriteString(TStringBuf input, EStringMode mode) noexcept;

        void DoWriteStringRaw(TStringBuf input, EStringMode mode) noexcept;

        void DoWriteStringHuffman(TStringBuf input, size_t encodedSize, EStringMode mode) noexcept;

        [[nodiscard]] static size_t GetHuffmanEncodedSize(
            TStringBuf input, EStringMode mode) noexcept;

    private:
        const THPackEncoderSettings Settings_;
        TBuffer ChunkBuffer_;
        TOutputRegion ChunkOutput_{ChunkBuffer_};
        TChunkList ChunkList_;
    };

}
