// File: /workspace/github_c_makefile_star2_O0/teodorst[P]app-huffman/huffman_decodification_mpi.c
// Function: huffman_decompress
int huffman_decompress(char* input_file_name, char* output_file_name, char *codification_file_name) {

	int myrank;
	int nr_proc;
	MPI_Status status;
	
	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
	MPI_Comm_size(MPI_COMM_WORLD, &nr_proc);

    FILE* codification_file = open_file(codification_file_name, "r");

    unsigned long long int nbits_buffer[nr_proc-1];
    int input_buffer_contors[nr_proc-1];

    size_t file_size = 0;
    int i, ret;
    char *buffer;
    int process_size = 0;
    char *input_buffer;
    char *output_buffer;

    char** codification = read_configuration_pthreads(codification_file, nbits_buffer, input_buffer_contors, &file_size);

    if (myrank == MASTER_PROCESS) {
    	FILE* input_file = open_file(input_file_name, "r");
	    FILE* output_file = open_file(output_file_name, "w");
    	
    	// compute input file size
		fseek(input_file, 0, SEEK_END);
		size_t compressed_file_size = ftell(input_file);
		int process_size = file_size / (nr_proc - 1);
		fseek(input_file, 0, SEEK_SET);


		int input_buffer_indexes[nr_proc-1];
		input_buffer_indexes[0] = 0;
		
		for (i = 1; i < nr_proc-1; i ++) {
			input_buffer_indexes[i] = input_buffer_indexes[i-1] + input_buffer_contors[i-1];
		}

	    input_buffer = (char*) malloc(file_size);
	    fread(input_buffer, 1, compressed_file_size, input_file);

	    for (i = 1; i < nr_proc; i ++) {
	    	MPI_Send(&process_size, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
	    	MPI_Send(input_buffer_contors + i - 1, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
	    	MPI_Send(nbits_buffer + i - 1, 1, MPI_UNSIGNED_LONG, i, 0, MPI_COMM_WORLD);
	    	MPI_Send(input_buffer + input_buffer_indexes[i-1], input_buffer_contors[i-1], MPI_CHAR, i, 0, MPI_COMM_WORLD);
	    	printf("%d a trimis toate 4 catre %d\n", myrank, i);
	    }

	    for (i = 1; i < nr_proc; i ++) {
	    	MPI_Recv(input_buffer + (i-1) * process_size, process_size, MPI_CHAR, i, 0, MPI_COMM_WORLD, &status);
	    }

	   	fwrite(input_buffer, 1, file_size, output_file);

	    // close files
	    fclose(input_file);
	    fclose(output_file);
	    fclose(codification_file);

	}
    else {
    	
		/* for each codification find the leaf and save it into a buffer */
	    node_t* root = build_huffman_tree_from_codification(codification);
	    printf("Got the tree\n");

	    int input_buffer_contor = 0;
	    unsigned long long int nbits = 0;

	    MPI_Recv(&process_size, 1, MPI_INT, MASTER_PROCESS, 0, MPI_COMM_WORLD, &status);
		MPI_Recv(&input_buffer_contor, 1, MPI_INT, MASTER_PROCESS, 0, MPI_COMM_WORLD, &status);
		MPI_Recv(&nbits, 1, MPI_UNSIGNED_LONG, MASTER_PROCESS, 0, MPI_COMM_WORLD, &status);	 

		input_buffer = (char*) malloc(input_buffer_contor);
   		output_buffer = (char*) malloc(process_size);

	    MPI_Recv(input_buffer, input_buffer_contor, MPI_CHAR, MASTER_PROCESS, 0, MPI_COMM_WORLD, &status);
	   	printf("%d a primit toate 4 de la %d: %d %d %llu\n", myrank, MASTER_PROCESS, process_size, input_buffer_contor, nbits);


	    decode_bytes_for_chunk_pthreads(root, input_buffer, nbits, output_buffer);

	    MPI_Send(output_buffer, process_size, MPI_CHAR, MASTER_PROCESS, 0, MPI_COMM_WORLD);
    }


	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq 0x3c42(%rip), %rdi      # 0x4fe0
movq %rdi, -0xf0(%rbp)
leaq -0x1c(%rbp), %rsi
callq 0x1150
movq -0xf0(%rbp), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1100
movq -0x18(%rbp), %rdi
leaq 0x1c3b(%rip), %rsi      # 0x3004
callq 0x12e0
movq %rax, -0x40(%rbp)
movl -0x20(%rbp), %eax
decl %eax
movq %rsp, %rcx
movq %rcx, -0x48(%rbp)
leaq 0xf(,%rax,8), %rcx
andq $-0x10, %rcx
movq %rsp, %rsi
subq %rcx, %rsi
movq %rsi, -0xe8(%rbp)
movq %rsi, %rsp
movq %rax, -0x50(%rbp)
movl -0x20(%rbp), %eax
decl %eax
leaq 0xf(,%rax,4), %rcx
andq $-0x10, %rcx
movq %rsp, %rdx
subq %rcx, %rdx
movq %rdx, -0xe0(%rbp)
movq %rdx, %rsp
movq %rax, -0x58(%rbp)
movq $0x0, -0x60(%rbp)
movl $0x0, -0x74(%rbp)
movq -0x40(%rbp), %rdi
leaq -0x60(%rbp), %rcx
callq 0x2710
movq %rax, -0x90(%rbp)
cmpl $0x0, -0x1c(%rbp)
jne 0x1744
movq -0x8(%rbp), %rdi
leaq 0x1ba9(%rip), %rsi      # 0x3004
callq 0x12e0
movq %rax, -0x98(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x1b94(%rip), %rsi      # 0x3006
callq 0x12e0
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
xorl %eax, %eax
movl %eax, -0xfc(%rbp)
movl %eax, %esi
movq %rsi, -0x108(%rbp)
movl $0x2, %edx
callq 0x1080
movq -0x98(%rbp), %rdi
callq 0x1060
movq -0x108(%rbp), %rsi
movq %rax, -0xa8(%rbp)
movq -0x60(%rbp), %rax
movl -0x20(%rbp), %ecx
decl %ecx
movslq %ecx, %rcx
movq %rsi, %rdx
divq %rcx
movl -0xfc(%rbp), %edx
movl %eax, -0xac(%rbp)
movq -0x98(%rbp), %rdi
callq 0x1080
movl -0x20(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rsp, %rax
movq %rax, -0xb8(%rbp)
leaq 0xf(,%rcx,4), %rdx
andq $-0x10, %rdx
movq %rsp, %rax
subq %rdx, %rax
movq %rax, -0xf8(%rbp)
movq %rax, %rsp
movq %rcx, -0xc0(%rbp)
movl $0x0, (%rax)
movl $0x1, -0x64(%rbp)
movl -0x64(%rbp), %eax
movl -0x20(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x156a
movq -0xf8(%rbp), %rax
movq -0xe0(%rbp), %rcx
movl -0x64(%rbp), %edx
subl $0x1, %edx
movslq %edx, %rdx
movl (%rax,%rdx,4), %edx
movl -0x64(%rbp), %esi
subl $0x1, %esi
movslq %esi, %rsi
addl (%rcx,%rsi,4), %edx
movslq -0x64(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x1525
movq -0x60(%rbp), %rdi
callq 0x10b0
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
movq -0xa8(%rbp), %rdx
movq -0x98(%rbp), %rcx
movl $0x1, %esi
callq 0x1140
movl $0x1, -0x64(%rbp)
movl -0x64(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x169c
movl -0x64(%rbp), %ecx
leaq -0xac(%rbp), %rdi
movl $0x1, %esi
movq 0x3a04(%rip), %rdx      # 0x4fc0
xorl %r8d, %r8d
movq 0x3a1a(%rip), %r9       # 0x4fe0
callq 0x1030
movq -0xe0(%rbp), %rdi
movslq -0x64(%rbp), %rax
shlq $0x2, %rax
addq %rax, %rdi
addq $-0x4, %rdi
movl -0x64(%rbp), %ecx
movl $0x1, %esi
movq 0x39d0(%rip), %rdx      # 0x4fc0
xorl %r8d, %r8d
movq 0x39e6(%rip), %r9       # 0x4fe0
callq 0x1030
movq -0xe8(%rbp), %rdi
movslq -0x64(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $-0x8, %rdi
movl -0x64(%rbp), %ecx
movl $0x1, %esi
movq 0x39c4(%rip), %rdx      # 0x4fe8
xorl %r8d, %r8d
movq 0x39b2(%rip), %r9       # 0x4fe0
callq 0x1030
movq -0xf8(%rbp), %rcx
movq -0xe0(%rbp), %rax
movq -0x80(%rbp), %rdi
movl -0x64(%rbp), %edx
subl $0x1, %edx
movslq %edx, %rdx
movslq (%rcx,%rdx,4), %rcx
addq %rcx, %rdi
movl -0x64(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %esi
movl -0x64(%rbp), %ecx
movq 0x3945(%rip), %rdx      # 0x4fb0
xorl %r8d, %r8d
movq 0x396b(%rip), %r9       # 0x4fe0
callq 0x1030
movl -0x1c(%rbp), %esi
movl -0x64(%rbp), %edx
leaq 0x1981(%rip), %rdi      # 0x3008
movb $0x0, %al
callq 0x1040
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x159a
movl $0x1, -0x64(%rbp)
movl -0x64(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x16fb
movq -0x80(%rbp), %rdi
movl -0x64(%rbp), %eax
subl $0x1, %eax
imull -0xac(%rbp), %eax
cltq
addq %rax, %rdi
movl -0xac(%rbp), %esi
movl -0x64(%rbp), %ecx
movq 0x38df(%rip), %rdx      # 0x4fb0
xorl %r8d, %r8d
movq 0x3905(%rip), %r9       # 0x4fe0
leaq -0x38(%rbp), %rax
subq $0x10, %rsp
movq %rax, (%rsp)
callq 0x1130
addq $0x10, %rsp
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x16a3
movq -0x80(%rbp), %rdi
movq -0x60(%rbp), %rdx
movq -0xa0(%rbp), %rcx
movl $0x1, %esi
callq 0x11b0
movq -0x98(%rbp), %rdi
callq 0x11a0
movq -0xa0(%rbp), %rdi
callq 0x11a0
movq -0x40(%rbp), %rdi
callq 0x11a0
movq -0xb8(%rbp), %rax
movq %rax, %rsp
jmp 0x18ce
movq -0x90(%rbp), %rdi
callq 0x2a40
movq %rax, -0xc8(%rbp)
leaq 0x18c8(%rip), %rdi      # 0x3026
movb $0x0, %al
callq 0x1040
movl $0x0, -0xcc(%rbp)
movq $0x0, -0xd8(%rbp)
leaq -0x74(%rbp), %rdi
movl $0x1, %esi
movq 0x3836(%rip), %rdx      # 0x4fc0
xorl %r8d, %r8d
movq 0x384c(%rip), %r9       # 0x4fe0
leaq -0x38(%rbp), %rax
subq $0x10, %rsp
movl %r8d, %ecx
movq %rax, (%rsp)
callq 0x1130
addq $0x10, %rsp
leaq -0xcc(%rbp), %rdi
movl $0x1, %esi
movq 0x3801(%rip), %rdx      # 0x4fc0
xorl %r8d, %r8d
movq 0x3817(%rip), %r9       # 0x4fe0
leaq -0x38(%rbp), %rax
subq $0x10, %rsp
movl %r8d, %ecx
movq %rax, (%rsp)
callq 0x1130
addq $0x10, %rsp
leaq -0xd8(%rbp), %rdi
movl $0x1, %esi
movq 0x37f4(%rip), %rdx      # 0x4fe8
xorl %r8d, %r8d
movq 0x37e2(%rip), %r9       # 0x4fe0
leaq -0x38(%rbp), %rax
subq $0x10, %rsp
movl %r8d, %ecx
movq %rax, (%rsp)
callq 0x1130
addq $0x10, %rsp
movslq -0xcc(%rbp), %rdi
callq 0x10b0
movq %rax, -0x80(%rbp)
movslq -0x74(%rbp), %rdi
callq 0x10b0
movq %rax, -0x88(%rbp)
movq -0x80(%rbp), %rdi
movl -0xcc(%rbp), %esi
movq 0x3769(%rip), %rdx      # 0x4fb0
xorl %r8d, %r8d
movq 0x378f(%rip), %r9       # 0x4fe0
leaq -0x38(%rbp), %rax
subq $0x10, %rsp
movl %r8d, %ecx
movq %rax, (%rsp)
callq 0x1130
addq $0x10, %rsp
movl -0x1c(%rbp), %esi
movl -0x74(%rbp), %ecx
movl -0xcc(%rbp), %r8d
movq -0xd8(%rbp), %r9
leaq 0x17b0(%rip), %rdi      # 0x3034
xorl %edx, %edx
movb $0x0, %al
callq 0x1040
movq -0xc8(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0xd8(%rbp), %rdx
movq -0x88(%rbp), %rcx
callq 0x1cd0
movq -0x88(%rbp), %rdi
movl -0x74(%rbp), %esi
movq 0x36f4(%rip), %rdx      # 0x4fb0
xorl %r8d, %r8d
movq 0x371a(%rip), %r9       # 0x4fe0
movl %r8d, %ecx
callq 0x1030
movq -0x48(%rbp), %rax
movq %rax, %rsp
xorl %eax, %eax
movq %rbp, %rsp
popq %rbp
retq
nopl (%rax)