// File: Matheus-Aguilar[P]Huffman/Huffman.cpp
// Function: HuffmanTree::build(int const*)
void HuffmanTree::build(const int freq[256]){

    //Copying the frequencies
    for(int i = 0; i < 256; ++i)
        this->freq[i] = freq[i];

    //Priority queue of frequencies and roots to mantain the order of the trees
    priority_queue<pair<int, Node *>> pq;
    
    //Adding characters that appear at least once in the string
    for(int i = 0; i < 256; ++i){
        if(this->freq[i] > 0){
            //Priority and root the tree
            pq.push(make_pair(-freq[i], new Node(i)));
        }
    }

    //If the string is empty
    if(pq.size() == 0){
        root = NULL;
        return;
    }

    //Keeps merging trees until there is just one
    while(pq.size() > 1){
        
        //Remove the two ones without the highest priority
        pair<int, Node *> topTree1 = pq.top();
        pq.pop();
        pair<int, Node *> topTree2 = pq.top();
        pq.pop();

        /*Merge both nodes into a bigger tree*/

        //Add the frequencies of the smaller trees roots into the merged one
        pair<int, Node *> mergedTree = make_pair(topTree1.first + topTree2.first, new Node(0));
        //Highest priority tree becomes left child
        mergedTree.second->left = topTree1.second; 
        //Second highest becomes right child
        mergedTree.second->right = topTree2.second; 
        //Merged tree becomes the parent of the smaller ones
        topTree1.second->parent = topTree2.second->parent = mergedTree.second;

        //Add the merged node into the priority queue
        pq.push(mergedTree);
    }

    //Define the root of the Huffman Tree as the merge of all character trees
    root = pq.top().second;

    /*Build character codes*/

    /*File with only one type of character. This is a special case
    because the decompresion algorithm assumes that the root has at
    least one child*/
    if(root->left == NULL && root->right == NULL){
        code[root->character].push_back(0); //The code is 0 by default
        Node *aux = root; //Save the merged result
        root = new Node(0); //Set a new root of the tree
        root->left = aux; //Update the left child of the root
        return;
    }
    
    /*More than one type of character cases*/
    vector<bool> codeString;
    buildCodes(root, codeString); //Start from the root to build codes
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xe8(%rbp)
movl $0x0, -0x14(%rbp)
cmpl $0x100, -0x14(%rbp)     # imm = 0x100
jge 0x59c3
movq -0xe8(%rbp), %rax
movq -0x10(%rbp), %rcx
movslq -0x14(%rbp), %rdx
movl (%rcx,%rdx,4), %edx
movslq -0x14(%rbp), %rcx
movl %edx, 0x8(%rax,%rcx,4)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x5995
leaq -0x38(%rbp), %rdi
callq 0x6260
movl $0x0, -0x3c(%rbp)
cmpl $0x100, -0x3c(%rbp)     # imm = 0x100
jge 0x5aba
movq -0xe8(%rbp), %rax
movslq -0x3c(%rbp), %rcx
cmpl $0x0, 0x8(%rax,%rcx,4)
jle 0x5aaa
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
negl %eax
movl %eax, -0x54(%rbp)
movl $0x20, %edi
callq 0x2120
movq %rax, -0xf0(%rbp)
jmp 0x5a19
movq -0xf0(%rbp), %rdi
movsbl -0x3c(%rbp), %esi
callq 0x6310
jmp 0x5a2b
movq -0xf0(%rbp), %rax
movq %rax, -0x60(%rbp)
leaq -0x54(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x62e0
movq %rdx, -0x100(%rbp)
movl %eax, -0xf4(%rbp)
jmp 0x5a52
movq -0x100(%rbp), %rax
movl -0xf4(%rbp), %ecx
movl %ecx, -0x50(%rbp)
movq %rax, -0x48(%rbp)
leaq -0x38(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x6290
jmp 0x5a75
jmp 0x5aaa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x5db0
movq -0xf0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
movl $0x20, %esi
callq 0x2130
jmp 0x5db0
jmp 0x5aac
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x59d3
leaq -0x38(%rbp), %rdi
callq 0x6350
movq %rax, -0x108(%rbp)
jmp 0x5acc
movq -0x108(%rbp), %rax
cmpq $0x0, %rax
jne 0x5af3
movq -0xe8(%rbp), %rax
movq $0x0, (%rax)
movl $0x1, -0x70(%rbp)
jmp 0x5d86
jmp 0x5af5
leaq -0x38(%rbp), %rdi
callq 0x6350
movq %rax, -0x110(%rbp)
jmp 0x5b07
movq -0x110(%rbp), %rax
cmpq $0x1, %rax
jbe 0x5c62
leaq -0x38(%rbp), %rdi
callq 0x6370
movq %rax, -0x118(%rbp)
jmp 0x5b2a
movq -0x118(%rbp), %rax
movups (%rax), %xmm0
movaps %xmm0, -0x80(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x6390
jmp 0x5b43
leaq -0x38(%rbp), %rdi
callq 0x6370
movq %rax, -0x120(%rbp)
jmp 0x5b55
movq -0x120(%rbp), %rax
movups (%rax), %xmm0
movaps %xmm0, -0x90(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x6390
jmp 0x5b71
movl -0x80(%rbp), %eax
movl -0x90(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0xa4(%rbp)
movl $0x20, %edi
callq 0x2120
movq %rax, -0x128(%rbp)
jmp 0x5b95
movq -0x128(%rbp), %rdi
xorl %esi, %esi
callq 0x6310
jmp 0x5ba5
movq -0x128(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0xa4(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x62e0
movq %rdx, -0x138(%rbp)
movl %eax, -0x12c(%rbp)
jmp 0x5bd5
movq -0x138(%rbp), %rax
movl -0x12c(%rbp), %ecx
movl %ecx, -0xa0(%rbp)
movq %rax, -0x98(%rbp)
movq -0x78(%rbp), %rcx
movq -0x98(%rbp), %rax
movq %rcx, (%rax)
movq -0x88(%rbp), %rcx
movq -0x98(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x98(%rbp), %rcx
movq -0x88(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x78(%rbp), %rax
movq %rcx, 0x10(%rax)
leaq -0x38(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x63e0
jmp 0x5c3b
jmp 0x5af5
movq -0x128(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
movl $0x20, %esi
callq 0x2130
jmp 0x5db0
leaq -0x38(%rbp), %rdi
callq 0x6370
movq %rax, -0x140(%rbp)
jmp 0x5c74
movq -0xe8(%rbp), %rax
movq -0x140(%rbp), %rcx
movq 0x8(%rcx), %rcx
movq %rcx, (%rax)
movq (%rax), %rax
cmpq $0x0, (%rax)
jne 0x5d48
movq -0xe8(%rbp), %rax
movq (%rax), %rax
cmpq $0x0, 0x8(%rax)
jne 0x5d48
movq -0xe8(%rbp), %rax
movq (%rax), %rcx
movzbl 0x18(%rcx), %ecx
leaq (%rcx,%rcx,4), %rcx
leaq 0x408(%rax,%rcx,8), %rdi
xorl %esi, %esi
callq 0x2ea0
jmp 0x5cce
movq -0xe8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xb8(%rbp)
movl $0x20, %edi
callq 0x2120
movq %rax, -0x148(%rbp)
jmp 0x5cf2
movq -0x148(%rbp), %rdi
xorl %esi, %esi
callq 0x6310
jmp 0x5d02
movq -0xe8(%rbp), %rax
movq -0x148(%rbp), %rcx
movq %rcx, (%rax)
movq -0xb8(%rbp), %rcx
movq (%rax), %rax
movq %rcx, (%rax)
movl $0x1, -0x70(%rbp)
jmp 0x5d86
movq -0x148(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
movl $0x20, %esi
callq 0x2130
jmp 0x5db0
leaq -0xe0(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0x2dd0
movq -0xe8(%rbp), %rdi
movq -0x150(%rbp), %rdx
movq (%rdi), %rsi
callq 0x5f40
jmp 0x5d73
leaq -0xe0(%rbp), %rdi
callq 0x3000
movl $0x0, -0x70(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x6430
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x3000
leaq -0x38(%rbp), %rdi
callq 0x6430
movq -0x68(%rbp), %rdi
callq 0x21e0
nopw %cs:(%rax,%rax)