#pragma once

#include "BitStream.h"
#include "HuffmanCodeLengthTable.h"

#include <vector>
#include <string>


class HuffmanStream
{

public:
    HuffmanStream(BitStream* inputStream, BitStream* outputStream);

    bool decode();

    void generateFixedCodeMapping();

    void setCodeLengthAlphabetLengths(const std::vector<unsigned char>& lengths);

private:
    void readCodingsTable();

    void readCodeLengths();

    void readSymbols();

    void copyFromBuffer(unsigned length, unsigned distance);

    bool readNextLiteralSymbol(unsigned& buffer);

    bool readNextDistanceSymbol(unsigned& buffer);

    bool readNextCodeLengthSymbol(unsigned& buffer);

    void addValue(unsigned value, unsigned& count, unsigned& lastValue, std::vector<unsigned char>& literals, unsigned numLiterals, std::vector<unsigned char>& distances);

    BitStream* mInputStream;
    BitStream* mOutputStream;

    std::vector<unsigned> mBuffer;

    unsigned mNumLiterals{0}; // HLIT + 257
    unsigned mNumDistances{0}; // HDIST + 1

    bool mUsingFixedCodes{false};
    HuffmanCodeLengthTable mCodeLengthTable;
    HuffmanCodeLengthTable mLiteralTable;
    HuffmanCodeLengthTable mDistanceTable;
};
