// File: irakr[P]Minimal-File-Compression-Tool/src/compression-driver.cpp
// Function: CompressionDriver::decompress(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&)
void CompressionDriver :: decompress(std::string &ifilename) {
	Log(this, "Started...");
	if(!m_Compressor) {
		Log(this, "[Fatal Error] No compression algorithm registered.");
		return; // FIXME... Throw an exception from here
	}

	std::cout << "Input File: " << ifilename << std::endl;

	// Output filename
	// (XXX) For now this is the auto generated output file name
	std::string ofilename = ifilename + ".orig";

	// TODO ...
	// Open file named 'file'
	// Pass the handle to specific decode() function
	// decode() should return back the decompressed file handle
	std::fstream inputf(ifilename, std::fstream::in | std::fstream::binary);
	if(!inputf.is_open()) {
		std::cerr << "[Error] The file \"" << ifilename << "\" does not exist." << std::endl;
		return;
	}
	
	fsize_t file_size = getFileSize(inputf);
    std::cout << "Size: " << file_size << " bytes" << std::endl;
    
	// Read bytes from input file
	byte *in_data_byte_buff = new byte[file_size + 1];
	inputf.read((char*)in_data_byte_buff, file_size);
	in_data_byte_buff[file_size] = 0; // Append null at the end because read() doesn't
	//std::cout << "file_buff: " << in_data_byte_buff << std::endl;

	// Get the compressed byte stream
	byte* decompressed_buff = m_Compressor->decoder().decode(in_data_byte_buff, &file_size);
	if(!decompressed_buff) {
	    // TODO... Cleanup code like should be placed somewhere else systematically.
	    Logf(this, "Error: Invalid file format.");
	    delete[] in_data_byte_buff;
	    inputf.close();
	    return;
	}
	std::cout << "Decompressed size = " << file_size << " bytes" << std::endl;

	// Open output file. The size will be obviously less than or impossibly
	// equal to the input file size;
	// Then write the compressed byte stream to it.
	std::fstream outputf;
	outputf.open(ofilename, std::fstream::out | std::fstream::binary);
	outputf.write((const char*)decompressed_buff,
		file_size);

	inputf.close();
	outputf.close();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x510, %rsp            # imm = 0x510
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x480(%rbp)
cmpq $0x0, 0x38(%rax)
jne 0x8f0a
jmp 0x92cd
movq 0xb0af(%rip), %rdi      # 0x13fc0
leaq 0x4250(%rip), %rsi      # 0xd168
callq 0x3200
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x31e0
movq %rax, %rdi
movq 0xb06d(%rip), %rsi      # 0x13fa0
callq 0x3230
movq -0x10(%rbp), %rsi
leaq 0x4277(%rip), %rdx      # 0xd1ba
leaq -0x30(%rbp), %rdi
callq 0x7130
movq -0x10(%rbp), %rax
movq %rax, -0x490(%rbp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x95e0
movl %eax, -0x484(%rbp)
jmp 0x8f6e
movl -0x484(%rbp), %edx
movq -0x490(%rbp), %rsi
leaq -0x240(%rbp), %rdi
callq 0x33a0
jmp 0x8f89
leaq -0x240(%rbp), %rdi
callq 0x33c0
movb %al, -0x491(%rbp)
jmp 0x8f9d
movb -0x491(%rbp), %al
testb $0x1, %al
jne 0x9050
jmp 0x8fad
movq 0xb03c(%rip), %rdi      # 0x13ff0
leaq 0x4205(%rip), %rsi      # 0xd1c0
callq 0x3200
movq %rax, -0x4a0(%rbp)
jmp 0x8fc9
movq -0x4a0(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x31e0
movq %rax, -0x4a8(%rbp)
jmp 0x8fe2
movq -0x4a8(%rbp), %rdi
leaq 0x41e3(%rip), %rsi      # 0xd1d3
callq 0x3200
movq %rax, -0x4b0(%rbp)
jmp 0x8ffe
movq -0x4b0(%rbp), %rdi
movq 0xaf94(%rip), %rsi      # 0x13fa0
callq 0x3230
jmp 0x9013
movl $0x1, -0x250(%rbp)
jmp 0x92b8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x9300
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x92f4
leaq -0x240(%rbp), %rdi
callq 0x8de0
movq %rax, -0x4b8(%rbp)
jmp 0x9065
movq -0x4b8(%rbp), %rax
movq %rax, -0x258(%rbp)
movq 0xaf46(%rip), %rdi      # 0x13fc0
leaq 0x4118(%rip), %rsi      # 0xd199
callq 0x3200
movq %rax, -0x4c0(%rbp)
jmp 0x908f
movq -0x4c0(%rbp), %rdi
movq -0x258(%rbp), %rsi
callq 0x3410
movq %rax, -0x4c8(%rbp)
jmp 0x90ab
movq -0x4c8(%rbp), %rdi
leaq 0x40e7(%rip), %rsi      # 0xd1a0
callq 0x3200
movq %rax, -0x4d0(%rbp)
jmp 0x90c7
movq -0x4d0(%rbp), %rdi
movq 0xaecb(%rip), %rsi      # 0x13fa0
callq 0x3230
jmp 0x90dc
movq -0x258(%rbp), %rdi
incq %rdi
callq 0x3030
movq %rax, -0x4d8(%rbp)
jmp 0x90f4
movq -0x4d8(%rbp), %rax
movq %rax, -0x260(%rbp)
movq -0x260(%rbp), %rsi
movq -0x258(%rbp), %rdx
leaq -0x240(%rbp), %rdi
callq 0x32c0
jmp 0x911e
movq -0x480(%rbp), %rax
movq -0x260(%rbp), %rcx
movq -0x258(%rbp), %rdx
movb $0x0, (%rcx,%rdx)
movq 0x38(%rax), %rdi
callq 0x9720
movq %rax, -0x4e0(%rbp)
jmp 0x9149
movq -0x4e0(%rbp), %rdi
movq -0x260(%rbp), %rsi
movq (%rdi), %rax
movq (%rax), %rax
leaq -0x258(%rbp), %rdx
callq *%rax
movq %rax, -0x4e8(%rbp)
jmp 0x916f
movq -0x4e8(%rbp), %rax
movq %rax, -0x268(%rbp)
cmpq $0x0, -0x268(%rbp)
jne 0x91c4
movq -0x260(%rbp), %rax
movq %rax, -0x4f0(%rbp)
cmpq $0x0, %rax
je 0x91a7
movq -0x4f0(%rbp), %rdi
callq 0x32d0
leaq -0x240(%rbp), %rdi
callq 0x3050
jmp 0x91b5
movl $0x1, -0x250(%rbp)
jmp 0x92b8
movq 0xadf5(%rip), %rdi      # 0x13fc0
leaq 0x4013(%rip), %rsi      # 0xd1e5
callq 0x3200
movq %rax, -0x4f8(%rbp)
jmp 0x91e0
movq -0x4f8(%rbp), %rdi
movq -0x258(%rbp), %rsi
callq 0x3410
movq %rax, -0x500(%rbp)
jmp 0x91fc
movq -0x500(%rbp), %rdi
leaq 0x3f96(%rip), %rsi      # 0xd1a0
callq 0x3200
movq %rax, -0x508(%rbp)
jmp 0x9218
movq -0x508(%rbp), %rdi
movq 0xad7a(%rip), %rsi      # 0x13fa0
callq 0x3230
jmp 0x922d
leaq -0x478(%rbp), %rdi
callq 0x3290
jmp 0x923b
movl $0x10, %edi
movl $0x4, %esi
callq 0x95e0
movl %eax, -0x50c(%rbp)
jmp 0x9252
movl -0x50c(%rbp), %edx
leaq -0x478(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x3320
jmp 0x926a
leaq -0x468(%rbp), %rdi
movq -0x268(%rbp), %rsi
movq -0x258(%rbp), %rdx
callq 0x32e0
jmp 0x9286
leaq -0x240(%rbp), %rdi
callq 0x3050
jmp 0x9294
leaq -0x478(%rbp), %rdi
callq 0x3050
jmp 0x92a2
leaq -0x478(%rbp), %rdi
callq 0x3090
movl $0x0, -0x250(%rbp)
leaq -0x240(%rbp), %rdi
callq 0x3090
leaq -0x30(%rbp), %rdi
callq 0x3150
addq $0x510, %rsp            # imm = 0x510
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
leaq -0x478(%rbp), %rdi
callq 0x3090
leaq -0x240(%rbp), %rdi
callq 0x3090
leaq -0x30(%rbp), %rdi
callq 0x3150
movq -0x248(%rbp), %rdi
callq 0x33e0
nopw %cs:(%rax,%rax)