// File: /workspace/github_c_makefile_star2_O3/teodorst[P]app-huffman/huffman_serial.c
// Function: huffman_compress
int huffman_compress(char* input_filename, char* output_filename, char* codification_filename) {
    char** codification = (char**) calloc(128, sizeof(char*));

    FILE* input_fp = open_file(input_filename, "r");
    FILE* codification_fp = open_file(codification_filename, "w");
    FILE* output_fp = open_file(output_filename, "w");

    // compute input file size
    fseek(input_fp, 0, SEEK_END);
    unsigned long long int size = ftell(input_fp);
    fseek(input_fp, 0, SEEK_SET);

    int i;
    char *input_file_buffer = (char*) malloc(size);
    char *output_file_buffer = (char*) malloc(size);

    // read input file //
    fread(input_file_buffer, 1, size, input_fp);

    unsigned long long int *frequency = (unsigned long long int*) calloc(128, sizeof(unsigned long long int));

    // compute frequency
    for (i = 0; i < size; i ++) {
        frequency[(unsigned char)input_file_buffer[i]] ++;
    }
    // create huffman_tree
    node_t* root_holder = build_huffman_tree(frequency);
    char path[MAX_BITS_CODE];
    find_codification(root_holder, path, 0, codification);

    int output_buffer_contor = 0;
    char output_char = 0;
    int contor = 7;
    unsigned long long int bits = 0;

    // time_t start = time(NULL);

    write_codification_for_chunk(input_file_buffer, size, codification, output_file_buffer, &output_buffer_contor, &output_char, &contor, &bits);

    // printf("%.2f\n", (double)(time(NULL) - start));

    fwrite(output_file_buffer, 1, output_buffer_contor, output_fp);
    if (output_char != 0) {
        fwrite(&output_char, 1, 1, output_fp);
    }

    write_metadata_file_serial(codification_fp, codification, bits);

	fclose(input_fp);
	fclose(output_fp);
    fclose(codification_fp);

    free_codification_matrix(codification);
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rdx, %r12
movq %rsi, %r15
movq %rdi, %r14
movl $0x80, %edi
movl $0x8, %esi
callq 0x10e0
movq %rax, %rbx
leaq 0x1bfb(%rip), %rsi      # 0x3004
movq %r14, %rdi
callq 0x1160
testq %rax, %rax
je 0x15a9
movq %rax, %r14
leaq 0x1be2(%rip), %rsi      # 0x3006
movq %r12, %rdi
callq 0x1160
testq %rax, %rax
je 0x15a9
movq %rax, %r12
leaq 0x1bc7(%rip), %rsi      # 0x3006
movq %r15, %rdi
callq 0x1160
movq %rax, 0x18(%rsp)
testq %rax, %rax
je 0x15a9
movq %r12, 0x10(%rsp)
movq %r14, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x1140
movq %r14, %rdi
callq 0x1110
movq %rax, %r13
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x1140
movq %r13, %rdi
callq 0x1120
movq %rax, %r15
movq %r13, %rdi
callq 0x1120
movq %rax, %rbp
movl $0x1, %esi
movq %r15, %rdi
movq %r13, %rdx
movq %r14, %rcx
callq 0x1070
movl $0x80, %edi
movl $0x8, %esi
callq 0x10e0
testq %r13, %r13
je 0x14d0
xorl %ecx, %ecx
movzbl (%r15,%rcx), %edx
incq (%rax,%rdx,8)
incq %rcx
cmpq %rcx, %r13
jne 0x14bf
movq %rax, %rdi
callq 0x24d8
leaq 0x30(%rsp), %rsi
movq %rax, %rdi
xorl %edx, %edx
movq %rbx, %rcx
callq 0x231a
movq %rbx, %rdx
leaq 0x2c(%rsp), %rbx
movl $0x0, (%rbx)
leaq 0xf(%rsp), %r12
movb $0x0, (%r12)
leaq 0x28(%rsp), %rax
movl $0x7, (%rax)
leaq 0x20(%rsp), %r10
movq $0x0, (%r10)
movq %r15, %rdi
movl %r13d, %esi
movq %rdx, %r15
movq %rbp, %rcx
movq %rbx, %r8
movq %r12, %r9
pushq %r10
pushq %rax
callq 0x1d15
addq $0x10, %rsp
movslq (%rbx), %rdx
movl $0x1, %esi
movq %rbp, %rdi
movq 0x18(%rsp), %r13
movq %r13, %rcx
callq 0x11a0
movsbl (%r12), %edi
testl %edi, %edi
je 0x1560
movq %r13, %rsi
callq 0x10d0
movq 0x20(%rsp), %rdx
movq 0x10(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x1ed3
movq %r14, %rdi
callq 0x1080
movq %r13, %rdi
callq 0x1080
movq %r12, %rdi
callq 0x1080
movq %r15, %rdi
callq 0x13a3
xorl %eax, %eax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x1, %edi
callq 0x1190