// File: /workspace/github_c_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdx, %r15
movq %rsi, -0x38(%rbp)
movq %rdi, %rbx
movq 0x3c62(%rip), %r12      # 0x4fe0
leaq -0x30(%rbp), %rsi
movq %r12, %rdi
callq 0x1180
leaq -0x2c(%rbp), %rsi
movq %r12, %rdi
callq 0x1130
leaq 0x1c67(%rip), %rsi      # 0x3004
movq %r15, %rdi
callq 0x10e0
testq %rax, %rax
je 0x17c2
movq %rsp, %r15
movl -0x2c(%rbp), %ecx
decl %ecx
movq %rsp, %r12
leaq 0xf(,%rcx,8), %rcx
andq $-0x10, %rcx
subq %rcx, %r12
movq %r12, %rsp
movl -0x2c(%rbp), %ecx
decl %ecx
movq %rsp, %r13
leaq 0xf(,%rcx,4), %rcx
andq $-0x10, %rcx
subq %rcx, %r13
movq %r13, %rsp
leaq -0x58(%rbp), %rcx
movq $0x0, (%rcx)
movl $0x0, -0x3c(%rbp)
movq %rax, %r14
movq %rax, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x21b8
cmpl $0x0, -0x30(%rbp)
movq %r15, -0x88(%rbp)
je 0x156b
movq %rax, %rdi
callq 0x2434
movq %rax, -0x38(%rbp)
leaq 0x1c24(%rip), %rdi      # 0x3050
callq 0x1080
leaq -0x8c(%rbp), %r13
movl $0x0, (%r13)
leaq -0x48(%rbp), %r12
movq $0x0, (%r12)
subq $0x8, %rsp
leaq -0xa8(%rbp), %r14
movq 0x3b62(%rip), %rbx      # 0x4fc0
movq 0x3b7b(%rip), %r15      # 0x4fe0
leaq -0x3c(%rbp), %rdi
movl $0x1, %esi
movq %rbx, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r15, %r9
pushq %r14
callq 0x1160
addq $0x8, %rsp
movq %r13, %rdi
movl $0x1, %esi
movq %rbx, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r15, %r9
pushq %r14
callq 0x1160
addq $0x8, %rsp
movq 0x3b3f(%rip), %rdx      # 0x4fe8
movq %r12, %rdi
movl $0x1, %esi
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r15, %r9
pushq %r14
callq 0x1160
addq $0x10, %rsp
movl (%r13), %eax
movslq %eax, %r12
movq %r12, %rdi
callq 0x10d0
movq %rax, %r15
leaq -0x3c(%rbp), %r14
movslq (%r14), %rdi
callq 0x10d0
movq %rax, %rbx
subq $0x8, %rsp
movq 0x3ac0(%rip), %rdx      # 0x4fb0
movq %r15, %rdi
movl %r12d, %esi
xorl %ecx, %ecx
xorl %r8d, %r8d
movq 0x3ade(%rip), %r9       # 0x4fe0
leaq -0xa8(%rbp), %rax
pushq %rax
callq 0x1160
addq $0x10, %rsp
movl -0x30(%rbp), %esi
movl (%r14), %ecx
movl (%r13), %r8d
leaq -0x48(%rbp), %r12
movq (%r12), %r9
leaq 0x1afa(%rip), %rdi      # 0x3026
xorl %edx, %edx
xorl %eax, %eax
callq 0x1040
movq (%r12), %rdx
movq -0x38(%rbp), %rdi
movq %r15, %rsi
movq %rbx, %rcx
callq 0x19ef
movl (%r14), %esi
movq %rbx, %rdi
movq 0x3a5b(%rip), %rdx      # 0x4fb0
xorl %ecx, %ecx
xorl %r8d, %r8d
movq 0x3a7f(%rip), %r9       # 0x4fe0
callq 0x1030
jmp 0x17aa
movq %r14, -0x80(%rbp)
leaq 0x1a8e(%rip), %rsi      # 0x3004
movq %rbx, %rdi
callq 0x10e0
testq %rax, %rax
je 0x17c2
movq %rax, %r14
leaq 0x1a75(%rip), %rsi      # 0x3006
movq -0x38(%rbp), %rdi
callq 0x10e0
movq %rax, -0x78(%rbp)
testq %rax, %rax
je 0x17c2
xorl %ebx, %ebx
movq %r14, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x1090
movq %r14, %rdi
callq 0x1060
movq %rax, -0x68(%rbp)
movq -0x58(%rbp), %rax
movslq -0x2c(%rbp), %rcx
decq %rcx
xorl %edx, %edx
divq %rcx
movl %eax, -0x48(%rbp)
movq %r14, -0x60(%rbp)
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x1090
movq %rsp, -0x70(%rbp)
movl -0x2c(%rbp), %eax
decl %eax
movq %rsp, %rcx
leaq 0xf(,%rax,4), %rax
andq $-0x10, %rax
movq %rcx, %rdx
subq %rax, %rdx
movq %rdx, -0x38(%rbp)
movq %rdx, %rsp
negq %rax
movl $0x0, (%rcx,%rax)
movl -0x2c(%rbp), %eax
cmpl $0x3, %eax
jl 0x163b
movq %r13, %rdx
decl %eax
decq %rax
xorl %ecx, %ecx
movq -0x38(%rbp), %rsi
addl (%rdx,%rcx,4), %ebx
movl %ebx, 0x4(%rsi,%rcx,4)
incq %rcx
cmpq %rcx, %rax
jne 0x162c
movq -0x58(%rbp), %rdi
callq 0x10d0
movl $0x1, %r14d
movl $0x1, %esi
movq %rax, -0x50(%rbp)
movq %rax, %rdi
movq -0x68(%rbp), %rdx
movq -0x60(%rbp), %rcx
callq 0x1170
cmpl $0x2, -0x2c(%rbp)
jl 0x1773
leaq -0x48(%rbp), %rdi
movl $0x1, %esi
movq 0x3943(%rip), %rbx      # 0x4fc0
movq %rbx, %rdx
movl %r14d, %ecx
xorl %r8d, %r8d
movq %r12, %r15
movq 0x3950(%rip), %r12      # 0x4fe0
movq %r12, %r9
callq 0x1030
movq %r13, %rdi
movl $0x1, %esi
movq %rbx, %rdx
movq -0x38(%rbp), %rbx
movl %r14d, %ecx
xorl %r8d, %r8d
movq %r12, %r9
callq 0x1030
movq %r15, %rdi
movl $0x1, %esi
movq 0x3924(%rip), %rdx      # 0x4fe8
movl %r14d, %ecx
xorl %r8d, %r8d
movq %r12, %r9
callq 0x1030
movslq -0x4(%rbx,%r14,4), %rdi
addq -0x50(%rbp), %rdi
movl (%r13), %esi
movq 0x38ca(%rip), %rdx      # 0x4fb0
movl %r14d, %ecx
xorl %r8d, %r8d
movq %r12, %r9
movq %r15, %r12
callq 0x1030
movl -0x30(%rbp), %esi
leaq 0x1907(%rip), %rdi      # 0x3008
movl %r14d, %edx
xorl %eax, %eax
callq 0x1040
incq %r14
movslq -0x2c(%rbp), %rax
addq $0x4, %r13
addq $0x8, %r12
cmpq %rax, %r14
jl 0x166d
cmpl $0x2, %eax
jl 0x1773
movl $0x1, %ebx
leaq -0xa8(%rbp), %r15
movq 0x3875(%rip), %r14      # 0x4fb0
movq 0x389e(%rip), %r12      # 0x4fe0
leal -0x1(%rbx), %eax
movl -0x48(%rbp), %esi
imull %esi, %eax
movslq %eax, %rdi
addq -0x50(%rbp), %rdi
subq $0x8, %rsp
movq %r14, %rdx
movl %ebx, %ecx
xorl %r8d, %r8d
movq %r12, %r9
pushq %r15
callq 0x1160
addq $0x10, %rsp
incl %ebx
cmpl -0x2c(%rbp), %ebx
jl 0x1742
movq -0x58(%rbp), %rdx
movl $0x1, %esi
movq -0x50(%rbp), %rdi
movq -0x78(%rbp), %rbx
movq %rbx, %rcx
callq 0x11e0
movq -0x60(%rbp), %rdi
callq 0x11d0
movq %rbx, %rdi
callq 0x11d0
movq -0x80(%rbp), %rdi
callq 0x11d0
movq -0x70(%rbp), %rsp
movq -0x88(%rbp), %rsp
xorl %eax, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x1, %edi
callq 0x10b0