// File: /workspace/github_c_makefile_star2_O2/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, %r12
movq %rsi, -0x38(%rbp)
movq %rdi, %r14
movq 0x3c67(%rip), %rbx      # 0x4fe0
leaq -0x48(%rbp), %r15
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1180
leaq -0x2c(%rbp), %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1130
leaq 0x1c66(%rip), %rsi      # 0x3004
movq %r12, %rdi
callq 0x130c
movq %rax, %rbx
movq %rsp, -0x88(%rbp)
movl (%r13), %eax
decl %eax
movq %rsp, %r12
leaq 0xf(,%rax,8), %rax
andq $-0x10, %rax
subq %rax, %r12
movq %r12, %rsp
movl (%r13), %eax
decl %eax
movq %rsp, %r13
leaq 0xf(,%rax,4), %rax
andq $-0x10, %rax
subq %rax, %r13
movq %r13, %rsp
leaq -0x58(%rbp), %rcx
andq $0x0, (%rcx)
andl $0x0, -0x44(%rbp)
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x20d5
cmpl $0x0, (%r15)
je 0x1554
movq %rax, %rdi
callq 0x2335
movq %rax, -0x38(%rbp)
leaq 0x1c33(%rip), %rdi      # 0x3050
callq 0x1080
leaq -0x8c(%rbp), %r13
andl $0x0, (%r13)
leaq -0x40(%rbp), %rax
andq $0x0, (%rax)
subq $0x8, %rsp
leaq -0xa8(%rbp), %r14
movq 0x3b78(%rip), %rbx      # 0x4fc0
movq 0x3b91(%rip), %r12      # 0x4fe0
leaq -0x44(%rbp), %rdi
pushq $0x1
popq %r15
movl %r15d, %esi
movq %rbx, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r12, %r9
pushq %r14
callq 0x1160
popq %rcx
popq %rdx
subq $0x8, %rsp
movq %r13, %rdi
movl %r15d, %esi
movq %rbx, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r12, %r9
pushq %r14
callq 0x1160
popq %rcx
popq %rdx
subq $0x8, %rsp
movq 0x3b51(%rip), %rdx      # 0x4fe8
leaq -0x40(%rbp), %rdi
movl %r15d, %esi
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r12, %r9
pushq %r14
callq 0x1160
popq %rcx
popq %rdx
movl (%r13), %eax
movslq %eax, %r12
movq %r12, %rdi
callq 0x10d0
movq %rax, %r15
leaq -0x44(%rbp), %r14
movslq (%r14), %rdi
callq 0x10d0
movq %rax, %rbx
subq $0x8, %rsp
movq 0x3ad5(%rip), %rdx      # 0x4fb0
movq %r15, %rdi
movl %r12d, %esi
xorl %ecx, %ecx
xorl %r8d, %r8d
movq 0x3af3(%rip), %r9       # 0x4fe0
leaq -0xa8(%rbp), %rax
pushq %rax
callq 0x1160
popq %rcx
popq %rdx
movl -0x48(%rbp), %esi
movl (%r14), %ecx
movl (%r13), %r8d
leaq -0x40(%rbp), %r12
movq (%r12), %r9
leaq 0x1b11(%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 0x1976
movl (%r14), %esi
movq %rbx, %rdi
movq 0x3a72(%rip), %rdx      # 0x4fb0
xorl %ecx, %ecx
xorl %r8d, %r8d
movq 0x3a96(%rip), %r9       # 0x4fe0
callq 0x1030
jmp 0x176e
movq %r12, -0x60(%rbp)
movq %rbx, -0x80(%rbp)
leaq 0x1aa1(%rip), %rsi      # 0x3004
movq %r14, %rdi
callq 0x130c
movq %rax, %r14
leaq 0x1a91(%rip), %rsi      # 0x3006
movq -0x38(%rbp), %rdi
callq 0x130c
movq %rax, -0x78(%rbp)
xorl %ebx, %ebx
pushq $0x2
popq %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x1090
movq %r14, %rdi
callq 0x1060
movq %rax, -0x50(%rbp)
movq -0x58(%rbp), %rax
movslq -0x2c(%rbp), %rcx
decq %rcx
xorl %edx, %edx
divq %rcx
movl %eax, -0x40(%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, %rsp
negq %rax
andl $0x0, (%rcx,%rax)
movslq -0x2c(%rbp), %rax
decq %rax
pushq $0x1
popq %rcx
cmpq %rax, %rcx
jge 0x1600
addl -0x4(%r13,%rcx,4), %ebx
movl %ebx, (%rdx,%rcx,4)
incq %rcx
jmp 0x15ee
movq %rdx, -0x68(%rbp)
movq %r13, %r12
movq -0x58(%rbp), %rdi
callq 0x10d0
pushq $0x1
popq %rbx
movq %rax, -0x38(%rbp)
movq %rax, %rdi
movq %rbx, %rsi
movq -0x50(%rbp), %rdx
movq %r14, -0x50(%rbp)
movq %r14, %rcx
callq 0x1170
movslq -0x2c(%rbp), %rax
cmpq %rax, %rbx
jge 0x16e9
leaq -0x40(%rbp), %rdi
pushq $0x1
popq %r15
movl %r15d, %esi
movq 0x3974(%rip), %r14      # 0x4fc0
movq %r14, %rdx
movl %ebx, %ecx
xorl %r8d, %r8d
movq 0x3985(%rip), %r13      # 0x4fe0
movq %r13, %r9
callq 0x1030
movq %r12, %rdi
movl %r15d, %esi
movq %r14, %rdx
movl %ebx, %ecx
xorl %r8d, %r8d
movq %r13, %r9
callq 0x1030
movq -0x60(%rbp), %r15
movq %r15, %rdi
pushq $0x1
popq %rsi
movq 0x395e(%rip), %rdx      # 0x4fe8
movl %ebx, %ecx
xorl %r8d, %r8d
movq %r13, %r9
callq 0x1030
movq -0x68(%rbp), %r14
movslq (%r14), %rdi
addq -0x38(%rbp), %rdi
movl (%r12), %esi
movq 0x3903(%rip), %rdx      # 0x4fb0
movl %ebx, %ecx
xorl %r8d, %r8d
movq %r13, %r9
callq 0x1030
movl -0x48(%rbp), %esi
leaq 0x1944(%rip), %rdi      # 0x3008
movl %ebx, %edx
xorl %eax, %eax
callq 0x1040
incq %rbx
addq $0x4, %r14
movq %r14, -0x68(%rbp)
addq $0x4, %r12
addq $0x8, %r15
movq %r15, -0x60(%rbp)
jmp 0x162d
xorl %ecx, %ecx
leaq -0xa8(%rbp), %r12
movq 0x38b7(%rip), %rbx      # 0x4fb0
movq 0x38e0(%rip), %r14      # 0x4fe0
leal 0x1(%rcx), %r15d
cmpl %eax, %r15d
jge 0x1739
movl -0x40(%rbp), %esi
imull %esi, %ecx
movslq %ecx, %rdi
addq -0x38(%rbp), %rdi
subq $0x8, %rsp
movq %rbx, %rdx
movl %r15d, %ecx
xorl %r8d, %r8d
movq %r14, %r9
pushq %r12
callq 0x1160
addq $0x10, %rsp
movl -0x2c(%rbp), %eax
movl %r15d, %ecx
jmp 0x1700
movq -0x58(%rbp), %rdx
pushq $0x1
popq %rsi
movq -0x38(%rbp), %rdi
movq -0x78(%rbp), %rbx
movq %rbx, %rcx
callq 0x11e0
movq -0x50(%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