// File: irakr[P]Minimal-File-Compression-Tool/src/compression-driver.cpp
// Function: CompressionDriver::compress(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&)
void CompressionDriver :: compress(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 + ".compressed";

	// TODO ...
	// Open file named 'file'
	// Pass the handle to specific encode() function
	// encode() should return back the compressed file handle
	std::fstream inputf;
	inputf.open(ifilename, std::fstream::in | std::fstream::binary);
	if(!inputf.is_open()) {
		Logf(this, "[Error] The file \"%s\" does not exist.", ifilename.c_str());
		throw "fstream::open() failed.";
	}

	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* compressed_buff = m_Compressor->encoder().encode(in_data_byte_buff, &file_size);
	if(!compressed_buff) {
	    // TODO... Cleanup code like should be placed somewhere else systematically.
	    Logf(this, "Error: File too small to be compressed.");
	    delete[] in_data_byte_buff;
	    inputf.close();
	    return;
	}
	std::cout << "Compressed 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*)compressed_buff,
		file_size);

	inputf.close();
	outputf.close();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x500, %rsp            # imm = 0x500
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x488(%rbp)
cmpq $0x0, 0x38(%rax)
jne 0x8a0a
jmp 0x8d8e
movq 0xb5af(%rip), %rdi      # 0x13fc0
leaq 0x4750(%rip), %rsi      # 0xd168
callq 0x3200
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x31e0
movq %rax, %rdi
movq 0xb56d(%rip), %rsi      # 0x13fa0
callq 0x3230
movq -0x10(%rbp), %rsi
leaq 0x4732(%rip), %rdx      # 0xd175
leaq -0x30(%rbp), %rdi
callq 0x7130
leaq -0x240(%rbp), %rdi
callq 0x3290
jmp 0x8a5a
movq -0x10(%rbp), %rax
movq %rax, -0x498(%rbp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x95e0
movl %eax, -0x48c(%rbp)
jmp 0x8a7c
movl -0x48c(%rbp), %edx
movq -0x498(%rbp), %rsi
leaq -0x240(%rbp), %rdi
callq 0x3320
jmp 0x8a97
leaq -0x240(%rbp), %rdi
callq 0x33c0
movb %al, -0x499(%rbp)
jmp 0x8aab
movb -0x499(%rbp), %al
testb $0x1, %al
jne 0x8b11
jmp 0x8ab7
movl $0x8, %edi
callq 0x3110
movq %rax, %rdi
leaq 0x46b6(%rip), %rax      # 0xd181
movq %rax, (%rdi)
movq 0xb4d3(%rip), %rsi      # 0x13fa8
xorl %eax, %eax
movl %eax, %edx
callq 0x33b0
jmp 0x8dd6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x8dc1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x8db5
leaq -0x240(%rbp), %rdi
callq 0x8de0
movq %rax, -0x4a8(%rbp)
jmp 0x8b26
movq -0x4a8(%rbp), %rax
movq %rax, -0x258(%rbp)
movq 0xb485(%rip), %rdi      # 0x13fc0
leaq 0x4657(%rip), %rsi      # 0xd199
callq 0x3200
movq %rax, -0x4b0(%rbp)
jmp 0x8b50
movq -0x4b0(%rbp), %rdi
movq -0x258(%rbp), %rsi
callq 0x3410
movq %rax, -0x4b8(%rbp)
jmp 0x8b6c
movq -0x4b8(%rbp), %rdi
leaq 0x4626(%rip), %rsi      # 0xd1a0
callq 0x3200
movq %rax, -0x4c0(%rbp)
jmp 0x8b88
movq -0x4c0(%rbp), %rdi
movq 0xb40a(%rip), %rsi      # 0x13fa0
callq 0x3230
jmp 0x8b9d
movq -0x258(%rbp), %rdi
incq %rdi
callq 0x3030
movq %rax, -0x4c8(%rbp)
jmp 0x8bb5
movq -0x4c8(%rbp), %rax
movq %rax, -0x260(%rbp)
movq -0x260(%rbp), %rsi
movq -0x258(%rbp), %rdx
leaq -0x240(%rbp), %rdi
callq 0x32c0
jmp 0x8bdf
movq -0x488(%rbp), %rax
movq -0x260(%rbp), %rcx
movq -0x258(%rbp), %rdx
movb $0x0, (%rcx,%rdx)
movq 0x38(%rax), %rdi
callq 0x9600
movq %rax, -0x4d0(%rbp)
jmp 0x8c0a
movq -0x4d0(%rbp), %rdi
movq -0x260(%rbp), %rsi
movq (%rdi), %rax
movq (%rax), %rax
leaq -0x258(%rbp), %rdx
callq *%rax
movq %rax, -0x4d8(%rbp)
jmp 0x8c30
movq -0x4d8(%rbp), %rax
movq %rax, -0x268(%rbp)
cmpq $0x0, -0x268(%rbp)
jne 0x8c85
movq -0x260(%rbp), %rax
movq %rax, -0x4e0(%rbp)
cmpq $0x0, %rax
je 0x8c68
movq -0x4e0(%rbp), %rdi
callq 0x32d0
leaq -0x240(%rbp), %rdi
callq 0x3050
jmp 0x8c76
movl $0x1, -0x26c(%rbp)
jmp 0x8d79
movq 0xb334(%rip), %rdi      # 0x13fc0
leaq 0x4514(%rip), %rsi      # 0xd1a7
callq 0x3200
movq %rax, -0x4e8(%rbp)
jmp 0x8ca1
movq -0x4e8(%rbp), %rdi
movq -0x258(%rbp), %rsi
callq 0x3410
movq %rax, -0x4f0(%rbp)
jmp 0x8cbd
movq -0x4f0(%rbp), %rdi
leaq 0x44d5(%rip), %rsi      # 0xd1a0
callq 0x3200
movq %rax, -0x4f8(%rbp)
jmp 0x8cd9
movq -0x4f8(%rbp), %rdi
movq 0xb2b9(%rip), %rsi      # 0x13fa0
callq 0x3230
jmp 0x8cee
leaq -0x480(%rbp), %rdi
callq 0x3290
jmp 0x8cfc
movl $0x10, %edi
movl $0x4, %esi
callq 0x95e0
movl %eax, -0x4fc(%rbp)
jmp 0x8d13
movl -0x4fc(%rbp), %edx
leaq -0x480(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x3320
jmp 0x8d2b
leaq -0x470(%rbp), %rdi
movq -0x268(%rbp), %rsi
movq -0x258(%rbp), %rdx
callq 0x32e0
jmp 0x8d47
leaq -0x240(%rbp), %rdi
callq 0x3050
jmp 0x8d55
leaq -0x480(%rbp), %rdi
callq 0x3050
jmp 0x8d63
leaq -0x480(%rbp), %rdi
callq 0x3090
movl $0x0, -0x26c(%rbp)
leaq -0x240(%rbp), %rdi
callq 0x3090
leaq -0x30(%rbp), %rdi
callq 0x3150
addq $0x500, %rsp            # imm = 0x500
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
leaq -0x480(%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)