// File: /workspace/github_cpp_makefile_star2_O2/LandonSwartz[P]TheGreatEncryptor/main.cpp
// Function: main
int main(int argc, char*argv[])
{
	string filename;
	vector<string> fileContents;

	struct ft * args = new (struct ft);
	if(!args)
	{
		cerr<<"Memory allocation failed!"<<endl;
		exit(1);
	}
	args->fileVector = fileContents;

	hashing HashObj_encrypt;
	hashing HashObj_decrypt;

	// Using one variable for password may be confusing. This has been changed because in one instance,
	// a password is set, and in another, it is entered. Having separate variables should also improve
	// the overall security of the program.
	string password_set;
	string password_entered;

	// Create the base encryption class object
	encryption_base encryptionObj;
	encryption_base decryptionObj;

	pthread_t threads[NUM_THREADS];

	int choice;
	int exitCode = 1;
	int rc;

	int has_encrypted_once = 0;
	int has_decrypted_once = 0;

	//creating threads
	while(exitCode)
	{
		if (has_encrypted_once && has_decrypted_once)
			break;

		printMenu();
		cin>>choice;
		cin.ignore();
		cin.clear();

		switch(choice) {
			case 1:
				//read in file and prove that you've read it in
				//get size of file
				//divide into even chunks
				//send to the threads
				cout<<"What is the name of the file to hash?"<<endl;
				cin>>filename;
				cin.ignore();
				cin.clear();
				cout<<"You choose to read in the file: "<<filename<<endl;
				cout<<"If wrong then please read in again"<<endl;
				args->file.open(filename);
				rc = pthread_create(&threads[0], NULL, readFile, (void *)args);
				pthread_join(threads[0], NULL);
				break;
			case 2: 
				//encrypt file
				
				cout<<"What would you like the password to be?"<<endl;
				cin>>password_set;
				cin.ignore();
				cin.clear();
				cout<<"You entered: "<< password_set <<endl;
				HashObj_encrypt.set_password(password_set);
				HashObj_encrypt.set_hash_key_from_password();

				cout<<"Hash key is: "<<HashObj_encrypt.get_hash_key()<<endl;
				
				// Once the password has been retrieved, set the hash key in the encryption object
				encryptionObj.set_hash_key(HashObj_encrypt.get_hash_key());

				// The encryption class is ready to do some encryption. Give the class the data to work with.
				// Data being sent to this function should not already be encrypted.
				encryptionObj.set_decrypted_data(&(args->fileVector));

				// Call the getter function on the encryption object. Even if the data is not retrieved, calling
				// the getter function will perform the actual encryption. (This technically returns the address
				// of the agrs->fileVector retrieved earlier, but we already have it.)
				encryptionObj.get_encrypted_data();

				// Landon & Rushil, the data is modified in the vector, now what function do I call to update the file??
				/* 
				Call function here to update file based on the now modified vector
				*/
				rc = pthread_create(&threads[0], NULL, newFile, (void*)args);

				has_encrypted_once = 1;

				pthread_join(threads[0], NULL);
				
				break;
			case 3:
				//decrypt file

				cout << "Enter your password to decrypt the file: " << endl;
				cin >> password_entered;
				cin.ignore();
				cin.clear();
				cout << "You entered:" << password_entered << endl;
				HashObj_decrypt.set_password(password_entered);
				HashObj_decrypt.set_hash_key_from_password();

				// Set the hash key in the decryption object.
				decryptionObj.set_hash_key(HashObj_decrypt.get_hash_key());

				// Set the data based on what is stored in the file.
				decryptionObj.set_encrypted_data(&(args->fileVector));

				// Call the getter function to ensure the decryption happens.
				decryptionObj.get_decrypted_data();

				// Call the function necessary to overwrite the data in the file based on modifications made
				// to the vector which contains the file contents.
				rc = pthread_create(&threads[0], NULL, newFile, (void*)args);

				has_decrypted_once = 1;

				pthread_join(threads[0], NULL);
				break;
			case 4:
				//exit program
				exitCode = 0;
				break;
			default:
				//wrong choice
				cout<<"Please choose a choice between 1-4"<<endl;
				printMenu();
				break;
		}
	}

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
leaq 0xe0(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
andq $0x0, 0x30(%rsp)
movl $0x248, %edi            # imm = 0x248
callq 0x2180
movq %rax, %r13
movq %rax, %rdi
callq 0x2c8c
leaq 0x20(%rsp), %rsi
movq %r13, %rdi
callq 0x2cc2
leaq 0x70(%rsp), %rax
andl $0x0, -0x8(%rax)
leaq 0x80(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ebp, %ebp
leaq 0xf8(%rsp), %rcx
andl $0x0, -0x8(%rcx)
leaq 0x108(%rsp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb %bpl, (%rax)
movb %bpl, (%rcx)
leaq 0xc0(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
leaq 0xa0(%rsp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
leaq 0x50(%rsp), %rdx
andl $0x0, (%rdx)
movb %bpl, (%rax)
andl $0x0, 0x10(%rdx)
leaq 0x38(%rsp), %rax
andl $0x0, (%rax)
movb %bpl, (%rcx)
andl $0x0, 0x10(%rax)
movq %r13, %rax
addq $0x18, %rax
movq %rax, 0x18(%rsp)
movq 0x4816(%rip), %rbx      # 0x6fe0
movq 0x47ff(%rip), %r12      # 0x6fd0
leaq 0x158(%rsp), %r15
movl $0x0, 0x8(%rsp)
movq %rbp, 0x10(%rsp)
movq %r13, %r14
cmpl $0x0, 0x8(%rsp)
setne %r13b
andb %bpl, %r13b
jne 0x2b4a
callq 0x2667
movq %rbx, %rdi
leaq 0xc(%rsp), %rsi
callq 0x2110
movq %rbx, %rdi
callq 0x22b0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
xorl %esi, %esi
callq 0x2250
movl 0xc(%rsp), %eax
decl %eax
cmpl $0x3, %eax
ja 0x2911
movb $0x1, %bpl
leaq 0x17c5(%rip), %rcx      # 0x4004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %r12, %rdi
leaq 0x188d(%rip), %rsi      # 0x40df
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rbx, %rdi
leaq 0xd0(%rsp), %rsi
callq 0x21b0
movq %rbx, %rdi
callq 0x22b0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
xorl %esi, %esi
callq 0x2250
movq %r12, %rdi
leaq 0x1873(%rip), %rsi      # 0x4105
callq 0x2170
movq %rax, %rdi
leaq 0xd0(%rsp), %rsi
callq 0x2150
movq %rax, %rdi
callq 0x20d0
movq %r12, %rdi
leaq 0x186d(%rip), %rsi      # 0x4126
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %r15, %rdi
leaq 0xd0(%rsp), %rsi
callq 0x21e0
movq 0x18(%rsp), %rdi
movq %r15, %rbp
movq %r15, %rsi
callq 0x244c
movq %rbp, %rdi
callq 0x20c0
xorl %ebp, %ebp
movq %rsp, %rdi
xorl %esi, %esi
leaq -0x464(%rip), %rdx      # 0x2498
movq %r14, %rcx
callq 0x22a0
movq (%rsp), %rdi
xorl %esi, %esi
callq 0x2160
jmp 0x292f
movq %r12, %rdi
leaq 0x18a9(%rip), %rsi      # 0x41c4
callq 0x2170
movq %rax, %rdi
callq 0x20d0
callq 0x2667
xorl %ebp, %ebp
orb %r13b, %bpl
je 0x27fb
jmp 0x2b4a
movq %r12, %rdi
leaq 0x1846(%rip), %rsi      # 0x418d
callq 0x2170
movq 0x10(%rsp), %rbp
movq %r14, %r13
movq %rax, %rdi
callq 0x20d0
movq %rbx, %rdi
leaq 0x90(%rsp), %rsi
callq 0x21b0
movq %rbx, %rdi
callq 0x22b0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
xorl %esi, %esi
callq 0x2250
movq %r12, %rdi
leaq 0x1828(%rip), %rsi      # 0x41b7
callq 0x2170
movq %rax, %rdi
leaq 0x90(%rsp), %rsi
callq 0x2150
movq %rax, %rdi
callq 0x20d0
leaq 0x118(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x21e0
leaq 0xf8(%rsp), %rdi
leaq 0x118(%rsp), %r14
movq %r14, %rsi
callq 0x2100
movq %r14, %rdi
callq 0x20c0
leaq 0xf0(%rsp), %rdi
callq 0x2d8c
movl 0xf0(%rsp), %eax
movl %eax, 0x48(%rsp)
movl $0x1, 0x38(%rsp)
movq %r13, 0x40(%rsp)
leaq 0x38(%rsp), %rdi
callq 0x2dcc
movq %rsp, %rdi
xorl %esi, %esi
leaq -0x433(%rip), %rdx      # 0x25e9
movq %r13, %rcx
callq 0x22a0
movq (%rsp), %rdi
xorl %esi, %esi
callq 0x2160
pushq $0x1
popq %rax
movl %eax, 0x8(%rsp)
jmp 0x27e6
movq %r12, %rdi
leaq 0x1704(%rip), %rsi      # 0x4149
callq 0x2170
movq %r14, %r13
movq %rax, %rdi
callq 0x20d0
movq %rbx, %rdi
leaq 0xb0(%rsp), %rsi
callq 0x21b0
movq %rbx, %rdi
callq 0x22b0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
xorl %esi, %esi
callq 0x2250
movq %r12, %rdi
leaq 0x16e9(%rip), %rsi      # 0x4171
callq 0x2170
movq %rax, %rdi
leaq 0xb0(%rsp), %rsi
callq 0x2150
movq %rax, %rdi
callq 0x20d0
leaq 0x138(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x21e0
leaq 0x70(%rsp), %rdi
leaq 0x138(%rsp), %r14
movq %r14, %rsi
callq 0x2100
movq %r14, %rdi
callq 0x20c0
leaq 0x68(%rsp), %rdi
callq 0x2d8c
movq %r12, %rdi
leaq 0x1694(%rip), %rsi      # 0x417f
callq 0x2170
movl 0x68(%rsp), %esi
movq %rax, %rdi
callq 0x2280
movq %rax, %rdi
callq 0x20d0
movl 0x68(%rsp), %eax
movl %eax, 0x60(%rsp)
movl $0x2, 0x50(%rsp)
movq %r13, 0x58(%rsp)
leaq 0x50(%rsp), %rdi
callq 0x2daa
movq %rsp, %rdi
xorl %esi, %esi
leaq -0x546(%rip), %rdx      # 0x25e9
movq %r13, %rcx
callq 0x22a0
movb $0x1, %bpl
movq (%rsp), %rdi
xorl %esi, %esi
callq 0x2160
jmp 0x27e1
leaq 0x90(%rsp), %rdi
callq 0x20c0
leaq 0xb0(%rsp), %rdi
callq 0x20c0
leaq 0xf8(%rsp), %rdi
callq 0x20c0
leaq 0x70(%rsp), %rdi
callq 0x20c0
leaq 0x20(%rsp), %rdi
callq 0x2dee
leaq 0xd0(%rsp), %rdi
callq 0x20c0
xorl %eax, %eax
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
jmp 0x2be6
movq %rax, %rbx
leaq 0x138(%rsp), %rdi
jmp 0x2be6
movq %rax, %rbx
movl $0x248, %esi            # imm = 0x248
movq %r13, %rdi
callq 0x2190
jmp 0x2c21
movq %rax, %rbx
jmp 0x2c21
jmp 0x2bed
jmp 0x2bed
movq %rax, %rbx
leaq 0x158(%rsp), %rdi
callq 0x20c0
jmp 0x2bf0
movq %rax, %rbx
leaq 0x90(%rsp), %rdi
callq 0x20c0
leaq 0xb0(%rsp), %rdi
callq 0x20c0
leaq 0xf8(%rsp), %rdi
callq 0x20c0
leaq 0x70(%rsp), %rdi
callq 0x20c0
leaq 0x20(%rsp), %rdi
callq 0x2dee
leaq 0xd0(%rsp), %rdi
callq 0x20c0
movq %rbx, %rdi
callq 0x2290