// File: bcthomas[P]shrinksam/src/shrinksam.cpp
// Function: main
int main(int argc, char *argv[]) 
{
	locale loc("en_US");
	cout.imbue(loc);

	int c;                            // for getopt
	string input_name;                // input file name
	string shrunk_name;               // output file name
	bool delete_input = false;        // default to no delete
	bool using_stdin = true;          // default to true
	bool using_stdout = true;         // default to true
	bool unpaired = false;            // default to false, assumes paired

	Shrinksam::progname = argv[0];

//	if (argc < 2) {
//		show_usage(EXIT_FAILURE);
//	}

	while(1) {
		static struct option long_options[] =
		{
			{"verbose",      no_argument, 0, 'v'},
			{"version",      no_argument, 0, 'V'},
			{"help",         no_argument, 0, 'h'},
			{"delete-input", no_argument, 0, 'd'},
			{"unpaired",     no_argument, 0, 'u'},
			{"input",        required_argument, 0, 'i'},
			{"shrunk",       required_argument, 0, 'k'},
			{0, 0, 0, 0}
		};

		/* getopt_long stores the option index here. */
		int option_index = 0;

		c = getopt_long(argc, argv, "vVh?dui:k:", long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;

		switch (c) {
			case 'v':
				Shrinksam::verbose_flag = true;
				break;

			case 'V':
				/* version */
				cerr << "Version is " << Shrinksam::version << endl;
				return EXIT_FAILURE;
				break;

			case 'h':
				show_usage(EXIT_FAILURE);
				break;

			case '?':
				/* getopt_long already printed an error message. */
				break;

			case 'i':
				input_name = optarg;
				using_stdin = false;
				break;

			case 'k':
				shrunk_name = optarg;
				using_stdout = false;
				break;

			case 'd':
				delete_input = true;
				break;

			case 'u':
				unpaired = true;
				break;

			default:
				abort ();
		}
	}

	/* check validity of given argument set */
	if (delete_input) {
		if (input_name.empty()) {
			cerr << "Error: Input file name (-i) is required when using -d option." << endl;
			return EXIT_FAILURE;
		}
	}

	if (Shrinksam::verbose_flag) {
		if (using_stdin)
			cerr << "Input is coming from stdin" << endl;
		else
			cerr << "Input is from " << input_name << endl;

		if (using_stdout)
			cerr << "Shrunk SAM output will be to stdout" << endl;
		else
			cerr << "Shrunk SAM output will be in " << shrunk_name << endl;

		if (delete_input)
			cerr << "Input file will be deleted" << endl;
		if (unpaired)
			cerr << "Input is an unpaired SAM file" << endl;
	}

	ifstream input;
	if (using_stdin)
		input.open("/dev/stdin"); // I know - using this code will only work on unix systems
	else
		input.open(input_name);

	ofstream output;
	if (using_stdout)
		output.open("/dev/stdout"); // I know - using this code will only work on unix systems
	else
		output.open(shrunk_name);

	// process the data
	if (unpaired) {
		process_shrunk_unpaired(input,output);
	} else {
		process_shrunk(input,output);
	}

	// delete original file
	if (delete_input) {
		if (Shrinksam::verbose_flag)
			cerr << "Deleting " << input_name << "... " << endl;
		if (remove(input_name.c_str()) != 0)
			cerr << "ERROR: could not delete input file!" << endl;
		else {
			if (Shrinksam::verbose_flag)
				cerr << "Success!" << endl;
		}
	}

	fclose(stderr);
	fclose(stdout);
	fclose(stdin);
	return EXIT_SUCCESS;
}

// Assembly:
subq $0x518, %rsp            # imm = 0x518
movl $0x0, 0x514(%rsp)
movl %edi, 0x510(%rsp)
movq %rsi, 0x508(%rsp)
leaq 0x5a53(%rip), %rsi      # 0x936b
leaq 0x500(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x31f0
movq 0x88(%rsp), %rdx
movq 0x9684(%rip), %rsi      # 0xcfc0
movq (%rsi), %rax
movq -0x18(%rax), %rax
addq %rax, %rsi
leaq 0x4f8(%rsp), %rdi
callq 0x30a0
jmp 0x3955
leaq 0x4f8(%rsp), %rdi
callq 0x3380
leaq 0x4c8(%rsp), %rdi
callq 0x3370
leaq 0x4a8(%rsp), %rdi
callq 0x3370
movb $0x0, 0x4a7(%rsp)
movb $0x1, 0x4a6(%rsp)
movb $0x1, 0x4a5(%rsp)
movb $0x0, 0x4a4(%rsp)
movq 0x508(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x9a0a(%rip)      # 0xd3b8
jmp 0x39b0
movl $0x0, 0x4a0(%rsp)
movl 0x510(%rsp), %edi
movq 0x508(%rsp), %rsi
leaq 0x59cb(%rip), %rdx      # 0x939c
leaq 0x98c8(%rip), %rcx      # 0xd2a0
leaq 0x4a0(%rsp), %r8
callq 0x3420
movl %eax, 0x4e8(%rsp)
cmpl $-0x1, 0x4e8(%rsp)
jne 0x3a14
jmp 0x3b42
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4f0(%rsp)
movl %eax, 0x4ec(%rsp)
jmp 0x400d
movl 0x4e8(%rsp), %eax
addl $-0x3f, %eax
movl %eax, %ecx
movq %rcx, 0x80(%rsp)
subl $0x37, %eax
ja 0x3b38
movq 0x80(%rsp), %rax
leaq 0x55c4(%rip), %rcx      # 0x9004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movb $0x1, 0x9961(%rip)      # 0xd3b1
jmp 0x3b3d
movq 0x9594(%rip), %rdi      # 0xcff0
leaq 0x5944(%rip), %rsi      # 0x93a7
callq 0x3260
movq %rax, 0x78(%rsp)
jmp 0x3a6f
movq 0x78(%rsp), %rdi
movq 0x9815(%rip), %rsi      # 0xd290
callq 0x3260
movq %rax, 0x70(%rsp)
jmp 0x3a87
movq 0x70(%rsp), %rdi
movq 0x950d(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3a9a
movl $0x1, 0x514(%rsp)
movl $0x1, 0x49c(%rsp)
jmp 0x3fbd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4f0(%rsp)
movl %eax, 0x4ec(%rsp)
jmp 0x3ff3
movl $0x1, %edi
callq 0x3670
jmp 0x3ada
jmp 0x3b3d
jmp 0x3b3d
movq 0x94c3(%rip), %rax      # 0xcfa8
movq (%rax), %rsi
leaq 0x4c8(%rsp), %rdi
callq 0x3360
jmp 0x3af7
movb $0x0, 0x4a6(%rsp)
jmp 0x3b3d
movq 0x94a0(%rip), %rax      # 0xcfa8
movq (%rax), %rsi
leaq 0x4a8(%rsp), %rdi
callq 0x3360
jmp 0x3b1a
movb $0x0, 0x4a5(%rsp)
jmp 0x3b3d
movb $0x1, 0x4a7(%rsp)
jmp 0x3b3d
movb $0x1, 0x4a4(%rsp)
jmp 0x3b3d
callq 0x3150
jmp 0x39ae
testb $0x1, 0x4a7(%rsp)
je 0x3ba9
leaq 0x4c8(%rsp), %rdi
callq 0x3430
testb $0x1, %al
jne 0x3b5f
jmp 0x3ba7
movq 0x948a(%rip), %rdi      # 0xcff0
leaq 0x5846(%rip), %rsi      # 0x93b3
callq 0x3260
movq %rax, 0x68(%rsp)
jmp 0x3b79
movq 0x68(%rsp), %rdi
movq 0x941b(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3b8c
movl $0x1, 0x514(%rsp)
movl $0x1, 0x49c(%rsp)
jmp 0x3fbd
jmp 0x3ba9
testb $0x1, 0x9801(%rip)      # 0xd3b1
je 0x3d2c
testb $0x1, 0x4a6(%rsp)
je 0x3bef
movq 0x9429(%rip), %rdi      # 0xcff0
leaq 0x5823(%rip), %rsi      # 0x93f1
callq 0x3260
movq %rax, 0x60(%rsp)
jmp 0x3bda
movq 0x60(%rsp), %rdi
movq 0x93ba(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3bed
jmp 0x3c37
movq 0x93fa(%rip), %rdi      # 0xcff0
leaq 0x580f(%rip), %rsi      # 0x940c
callq 0x3260
movq %rax, 0x58(%rsp)
jmp 0x3c09
movq 0x58(%rsp), %rdi
leaq 0x4c8(%rsp), %rsi
callq 0x3250
movq %rax, 0x50(%rsp)
jmp 0x3c22
movq 0x50(%rsp), %rdi
movq 0x9372(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3c35
jmp 0x3c37
testb $0x1, 0x4a5(%rsp)
je 0x3c70
movq 0x93a8(%rip), %rdi      # 0xcff0
leaq 0x57cc(%rip), %rsi      # 0x941b
callq 0x3260
movq %rax, 0x48(%rsp)
jmp 0x3c5b
movq 0x48(%rsp), %rdi
movq 0x9339(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3c6e
jmp 0x3cb8
movq 0x9379(%rip), %rdi      # 0xcff0
leaq 0x57c1(%rip), %rsi      # 0x943f
callq 0x3260
movq %rax, 0x40(%rsp)
jmp 0x3c8a
movq 0x40(%rsp), %rdi
leaq 0x4a8(%rsp), %rsi
callq 0x3250
movq %rax, 0x38(%rsp)
jmp 0x3ca3
movq 0x38(%rsp), %rdi
movq 0x92f1(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3cb6
jmp 0x3cb8
testb $0x1, 0x4a7(%rsp)
je 0x3cf1
movq 0x9327(%rip), %rdi      # 0xcff0
leaq 0x578d(%rip), %rsi      # 0x945d
callq 0x3260
movq %rax, 0x30(%rsp)
jmp 0x3cdc
movq 0x30(%rsp), %rdi
movq 0x92b8(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3cef
jmp 0x3cf1
testb $0x1, 0x4a4(%rsp)
je 0x3d2a
movq 0x92ee(%rip), %rdi      # 0xcff0
leaq 0x576f(%rip), %rsi      # 0x9478
callq 0x3260
movq %rax, 0x28(%rsp)
jmp 0x3d15
movq 0x28(%rsp), %rdi
movq 0x927f(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3d28
jmp 0x3d2a
jmp 0x3d2c
leaq 0x290(%rsp), %rdi
callq 0x3300
jmp 0x3d3b
testb $0x1, 0x4a6(%rsp)
je 0x3d7b
leaq 0x574a(%rip), %rsi      # 0x9496
leaq 0x290(%rsp), %rdi
movl $0x8, %edx
callq 0x3190
jmp 0x3d60
jmp 0x3d99
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4f0(%rsp)
movl %eax, 0x4ec(%rsp)
jmp 0x3fae
leaq 0x290(%rsp), %rdi
leaq 0x4c8(%rsp), %rsi
movl $0x8, %edx
callq 0x3230
jmp 0x3d97
jmp 0x3d99
leaq 0x90(%rsp), %rdi
callq 0x3450
jmp 0x3da8
testb $0x1, 0x4a5(%rsp)
je 0x3df5
leaq 0x56e8(%rip), %rsi      # 0x94a1
leaq 0x90(%rsp), %rdi
movl $0x10, %edx
callq 0x3050
jmp 0x3dcd
jmp 0x3e13
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4f0(%rsp)
movl %eax, 0x4ec(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x33c0
jmp 0x3fae
leaq 0x90(%rsp), %rdi
leaq 0x4a8(%rsp), %rsi
movl $0x10, %edx
callq 0x3120
jmp 0x3e11
jmp 0x3e13
testb $0x1, 0x4a4(%rsp)
je 0x3e36
leaq 0x290(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x4660
jmp 0x3e34
jmp 0x3e4f
leaq 0x290(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x41f0
jmp 0x3e4d
jmp 0x3e4f
testb $0x1, 0x4a7(%rsp)
je 0x3f49
testb $0x1, 0x954d(%rip)      # 0xd3b1
je 0x3ec6
movq 0x9183(%rip), %rdi      # 0xcff0
leaq 0x5639(%rip), %rsi      # 0x94ad
callq 0x3260
movq %rax, 0x20(%rsp)
jmp 0x3e80
movq 0x20(%rsp), %rdi
leaq 0x4c8(%rsp), %rsi
callq 0x3250
movq %rax, 0x18(%rsp)
jmp 0x3e99
movq 0x18(%rsp), %rdi
leaq 0x5612(%rip), %rsi      # 0x94b7
callq 0x3260
movq %rax, 0x10(%rsp)
jmp 0x3eb1
movq 0x10(%rsp), %rdi
movq 0x90e3(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3ec4
jmp 0x3ec6
leaq 0x4c8(%rsp), %rdi
callq 0x30e0
movq %rax, %rdi
callq 0x34a0
cmpl $0x0, %eax
je 0x3f0f
movq 0x9109(%rip), %rdi      # 0xcff0
leaq 0x55ce(%rip), %rsi      # 0x94bc
callq 0x3260
movq %rax, 0x8(%rsp)
jmp 0x3efa
movq 0x8(%rsp), %rdi
movq 0x909a(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3f0d
jmp 0x3f47
testb $0x1, 0x949b(%rip)      # 0xd3b1
je 0x3f45
movq 0x90d1(%rip), %rdi      # 0xcff0
leaq 0x55ba(%rip), %rsi      # 0x94e0
callq 0x3260
movq %rax, (%rsp)
jmp 0x3f31
movq (%rsp), %rdi
movq 0x9064(%rip), %rsi      # 0xcfa0
callq 0x32b0
jmp 0x3f43
jmp 0x3f45
jmp 0x3f47
jmp 0x3f49
movq 0x9078(%rip), %rax      # 0xcfc8
movq (%rax), %rdi
callq 0x3270
jmp 0x3f5a
movq 0x902f(%rip), %rax      # 0xcf90
movq (%rax), %rdi
callq 0x3270
jmp 0x3f6b
movq 0x9046(%rip), %rax      # 0xcfb8
movq (%rax), %rdi
callq 0x3270
jmp 0x3f7c
movl $0x0, 0x514(%rsp)
movl $0x1, 0x49c(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x33c0
leaq 0x290(%rsp), %rdi
callq 0x3090
jmp 0x3fbd
leaq 0x290(%rsp), %rdi
callq 0x3090
jmp 0x3ff3
leaq 0x4a8(%rsp), %rdi
callq 0x3180
leaq 0x4c8(%rsp), %rdi
callq 0x3180
leaq 0x500(%rsp), %rdi
callq 0x3380
movl 0x514(%rsp), %eax
addq $0x518, %rsp            # imm = 0x518
retq
leaq 0x4a8(%rsp), %rdi
callq 0x3180
leaq 0x4c8(%rsp), %rdi
callq 0x3180
leaq 0x500(%rsp), %rdi
callq 0x3380
movq 0x4f0(%rsp), %rdi
callq 0x3470
nopw (%rax,%rax)