// File: /workspace/github_c_makefile_star2_O2/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 $0xc8, %rsp
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %r14
pushq $0x8
popq %rbp
movl $0x80, %edi
movq %rbp, %rsi
callq 0x10e0
movq %rax, 0x10(%rsp)
leaq 0x1ccd(%rip), %rsi      # 0x3004
movq %r14, %rdi
callq 0x12bc
movq %rax, %r14
leaq 0x1cbd(%rip), %r13      # 0x3006
movq %r15, %rdi
movq %r13, %rsi
callq 0x12bc
movq %rax, 0x28(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0x12bc
movq %rax, %r12
xorl %ebx, %ebx
pushq $0x2
popq %rdx
movq %r14, %rdi
xorl %esi, %esi
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, 0x18(%rsp)
pushq $0x1
popq %rsi
movq %r15, %rdi
movq %r13, %rdx
movq %r14, 0x20(%rsp)
movq %r14, %rcx
callq 0x1070
movl $0x80, %edi
movq %rbp, %rsi
callq 0x10e0
cmpq %rbx, %r13
je 0x13db
movzbl (%r15,%rbx), %ecx
incq (%rax,%rcx,8)
incq %rbx
jmp 0x13c8
movq %rax, %rdi
callq 0x2377
leaq 0x40(%rsp), %rsi
movq %rax, %rdi
xorl %edx, %edx
movq 0x10(%rsp), %rbp
movq %rbp, %rcx
callq 0x21d3
movq %r12, %r14
leaq 0x3c(%rsp), %r12
andl $0x0, (%r12)
leaq 0xf(%rsp), %rbx
movb $0x0, (%rbx)
leaq 0x38(%rsp), %rax
movl $0x7, (%rax)
leaq 0x30(%rsp), %r10
andq $0x0, (%r10)
movq %r15, %rdi
movl %r13d, %esi
movq %rbp, %rdx
movq 0x18(%rsp), %r15
movq %r15, %rcx
movq %r12, %r8
movq %rbx, %r9
pushq %r10
pushq %rax
callq 0x1c38
popq %rax
popq %rcx
movslq (%r12), %rdx
pushq $0x1
popq %rsi
movq %r15, %rdi
movq %r14, %rcx
callq 0x11a0
movsbl (%rbx), %edi
testl %edi, %edi
je 0x1465
movq %r14, %rsi
callq 0x10d0
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %r15
movq %r15, %rdi
movq 0x10(%rsp), %rbx
movq %rbx, %rsi
callq 0x1dd8
movq 0x20(%rsp), %rdi
callq 0x1080
movq %r14, %rdi
callq 0x1080
movq %r15, %rdi
callq 0x1080
movq %rbx, %rdi
callq 0x12d1
xorl %eax, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq