#include "Huffman.h"
#include "../common/Logging.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#define DECOMP_VAL_1 256
#define DECOMP_VAL_2 257

static uint8_t primes_0[256] = { // Compression type 0
    0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
static uint8_t primes_1[256] = { // Compression type 1
    0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, 0x0E, 0x0B, 0x14,
    0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04,
    0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03,
    0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
    0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02,
    0x02, 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03,
    0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0A, 0x02, 0x02, 0x03, 0x02,
    0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04,
    0x07, 0x09, 0x08, 0x0C, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
    0x01, 0x03, 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B};
static uint8_t primes_2[127] = { // Compression type 2
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02,
    0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01,
    0x02, 0x03, 0x03, 0x02, 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x01, 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, 0x10, 0x01,
    0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01};

static uint8_t primes_3[256] = { // Compression type 3
    0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, 0x09, 0x01, 0x01,
    0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x03, 0x01, 0x01, 0x01, 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03,
    0x03, 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, 0x02, 0x01,
    0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x0A, 0x02,
    0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11};

static uint8_t primes_4[16] = { // Compression type 4
    0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17};

static uint8_t primes_5[64] = { // Compression type 5
    0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
    0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
    0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
    0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18};

static uint8_t primes_6[130] = { // Compression type 6
    0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x46};

static uint8_t primes_7[130] = { // Compression type 7
    0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C,
    0xFB, 0x5C, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6C};

static uint8_t primes_8[130] = { // Compression type 8
    0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, 0xEE, 0xAF, 0xE4,
    0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23,
    0xDB, 0x49, 0xD0, 0x11, 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF,
    0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x9E};

static uint8_t *primes[] = {primes_0, primes_1, primes_2, primes_3, primes_4, primes_5, primes_6, primes_7, primes_8};
static int primes_len[]  = {sizeof(primes_0), sizeof(primes_1), sizeof(primes_2), sizeof(primes_3), sizeof(primes_4),
                            sizeof(primes_5), sizeof(primes_6), sizeof(primes_7), sizeof(primes_8)};

struct LinkedNode *huffman_create_linked_node(int decompressed_value, int weight) {
    struct LinkedNode *node = malloc(sizeof(struct LinkedNode));
    FAIL_IF_NULL(node);
    memset(node, 0, sizeof(struct LinkedNode));

    node->decompressed_value = decompressed_value;
    node->weight             = weight;

    return node;
}

struct LinkedNode *huffman_get_child1(struct LinkedNode *node) { return node->child_0->prev; }

struct LinkedNode *huffman_insert(struct LinkedNode *node, struct LinkedNode *other) {
    if (other->weight <= node->weight) {
        if (node->next != NULL) {
            node->next->prev = other;
            other->next      = node->next;
        }

        node->next  = other;
        other->prev = node;

        return other;
    }

    if (node->prev == NULL) {
        other->prev = NULL;
        node->prev  = other;
        other->next = node;
    } else {
        huffman_insert(node->prev, other);
    }

    return node;
}

struct LinkedNode *huffman_decode(struct BitReader *bit_reader, struct LinkedNode *head) {
    struct LinkedNode *node = head;

    while (node->child_0 != NULL) {
        int bit = BitReader_ReadBits(bit_reader, 1);
        if (bit == -1) {
            LOG_FATAL("Failed to decode huffman table!");
        }

        if (bit == 0) {
            node = node->child_0;
            continue;
        }

        node = huffman_get_child1(node);
    }

    return node;
}

struct LinkedNode *huffman_build_list(uint8_t *prime_table, int prime_len) {
    struct LinkedNode *root;

    root = huffman_create_linked_node(DECOMP_VAL_1, 1);
    root = huffman_insert(root, huffman_create_linked_node(DECOMP_VAL_2, 1));

    for (int i = 0; i < prime_len; i++) {
        if (prime_table[i] != 0) {
            root = huffman_insert(root, huffman_create_linked_node(i, prime_table[i]));
        }
    }

    return root;
}

struct LinkedNode *huffman_insert_node(struct LinkedNode *tail, int decomp) {
    struct LinkedNode *parent = tail;
    struct LinkedNode *result = tail->prev;

    struct LinkedNode *temp = huffman_create_linked_node(parent->decompressed_value, parent->weight);
    temp->parent            = parent;

    struct LinkedNode *new_node = huffman_create_linked_node(decomp, 0);
    new_node->parent            = parent;

    parent->child_0 = new_node;

    tail->next     = temp;
    temp->prev     = tail;
    new_node->prev = temp;
    temp->next     = new_node;

    huffman_adjust_tree(new_node);

    // NOTE: For compression type 0, adjust_tree should only be called once
    // for every value written, and only once here.
    huffman_adjust_tree(new_node);

    return result;
}
void huffman_adjust_tree(struct LinkedNode *new_node) {
    struct LinkedNode *current = new_node;

    while (current != NULL) {
        current->weight++;

        struct LinkedNode *insert_point;
        struct LinkedNode *prev;

        insert_point = current;

        while (true) {
            prev = insert_point->prev;
            if (prev == NULL) {
                break;
            }

            if (prev->weight >= current->weight) {
                break;
            }

            insert_point = prev;
        }

        if (insert_point == current) {
            current = current->parent;
            continue;
        }

        if (insert_point->prev != NULL) {
            insert_point->prev->next = insert_point->next;
        }

        insert_point->next->prev = insert_point->prev;
        insert_point->next       = current->next;
        insert_point->prev       = current;

        if (current->next != NULL) {
            current->next->prev = insert_point;
        }

        current->next = insert_point;

        current->prev->next = current->next;
        current->next->prev = current->prev;

        if (prev == NULL) {
            LOG_FATAL("Previous frame is undefined while adjusting huffman tree!");
        }

        struct LinkedNode *temp = prev->next;

        current->next = temp;
        current->prev = prev;
        temp->prev    = current;
        prev->next    = current;

        struct LinkedNode *current_parent = current->parent;
        struct LinkedNode *insert_parent  = insert_point->parent;

        if (current_parent->child_0 == current) {
            current_parent->child_0 = insert_point;
        }

        if (current_parent != insert_parent && insert_parent->child_0 == insert_point) {
            insert_parent->child_0 = current;
        }

        current->parent      = insert_parent;
        insert_point->parent = current_parent;

        current = current->parent;
    }
}
struct LinkedNode *huffman_build_tree(struct LinkedNode *tail) {
    struct LinkedNode *current = tail;

    while (current != NULL) {
        struct LinkedNode *child_0 = current;
        struct LinkedNode *child_1 = current->prev;

        if (child_1 == NULL) {
            break;
        }

        struct LinkedNode *parent = huffman_create_linked_node(0, child_0->weight + child_1->weight);

        parent->child_0 = child_0;
        child_0->parent = parent;
        child_1->parent = parent;

        huffman_insert(current, parent);
        current = current->prev->prev;
    }

    return current;
}
void huffman_free_linked_node(struct LinkedNode *node) {
    struct LinkedNode *next = node->next;
    free(node);
    node = next;
    while (node != NULL) {
        next = node->next;
        free(node);
        node = next;
    }
}

uint8_t *huffman_decompress(uint8_t *buffer, uint32_t buffer_len, uint32_t *result_size) {

    uint8_t comp_type = *buffer;
    buffer++;
    buffer_len--;

    if (comp_type < 1 || comp_type > 8) {
        LOG_FATAL("Invalid data while decompressing huffman table!");
    }

    struct LinkedNode *tail = huffman_build_list(primes[comp_type], primes_len[comp_type]);
    struct LinkedNode *head = huffman_build_tree(tail);

    *result_size = 0;

    uint32_t          current_result_capacity = 8;
    uint8_t          *result                  = calloc(current_result_capacity, 1);
    struct BitReader *bit_reader              = BitReader_Create(buffer, buffer_len);
    int               decoded;

    bool do_loop = true;
    while (do_loop) {
        struct LinkedNode *node = huffman_decode(bit_reader, head);
        decoded                 = node->decompressed_value;

        switch (decoded) {
        case DECOMP_VAL_1:
            do_loop = false;
            break;
        case DECOMP_VAL_2: {
            int new_value = BitReader_ReadBits(bit_reader, 8);
            if (new_value < 0) {
                LOG_FATAL("Failed to decompression huffman tree!");
            }
            *result_size += 1;
            if (*result_size >= current_result_capacity) {
                current_result_capacity <<= 1;
                result                    = realloc(result, current_result_capacity);
            }
            result[*result_size - 1] = new_value;
            tail                     = huffman_insert_node(tail, (uint8_t)new_value);
        } break;
        default:
            *result_size += 1;
            if (*result_size >= current_result_capacity) {
                current_result_capacity <<= 1;
                result                    = realloc(result, current_result_capacity);
            }

            result[*result_size - 1] = decoded;
        }
    }

    BitReader_Destroy(bit_reader);
    huffman_free_linked_node(head);
    return result;
}
