// File: gersteinlab[P]MUSIC/src/ms_genome_sequence_tools.cpp
// Function: extract_sequence(char*, char*, int, int, char, bool)
char* extract_sequence(char* chr_data_dir, char* raw_chr_name, int start, int end, char strand, bool upper_case)
{
	char chr_seq_fp[1000];
	sprintf(chr_seq_fp, "%s/%s.bin", chr_data_dir, raw_chr_name);
	FILE* f_chr = fopen(chr_seq_fp, "rb");

	if(f_chr == NULL)
	{
		// Try to fix the chromosome file path: Add 'chr' to beginning.
		sprintf(chr_seq_fp, "%s/%s.bin", chr_data_dir, raw_chr_name);
		f_chr = fopen(chr_seq_fp, "rb");

		if(f_chr == NULL)
		{
			fprintf(stderr, "Could not identify the conforming chromosome name from id %s, returning NULL.\n", raw_chr_name);
			return(NULL);
		}
	}

	// Read the binary sequence length.
	int l_bin_seq = 0;
	fread(&l_bin_seq, sizeof(int), 1, f_chr);

	int f_start = start - 1 + sizeof(int);
	//int f_end = end - 1;
	int f_end = f_start + (end-start);

	char* seq_buffer = NULL;

	if(f_start < f_end)
	{
		int length = (end - start + 1);

		seq_buffer = new char[length + 2];
		memset(seq_buffer, 0, sizeof(char) * (length + 1));

		// Go to the starting position.
		fseek(f_chr, f_start, SEEK_SET);

		// Fill the buffer.
		fread(seq_buffer, sizeof(char), length, f_chr);

		seq_buffer[length] = 0;
	} // start, end coparison.
	else
	{
		// Get the file size.
		fseek (f_chr, 0 , SEEK_END);
		int length = (int)(ftell(f_chr));
		
		seq_buffer = new char[length+2]; 
		memset(seq_buffer, 0, sizeof(char) * (length + 1));

		rewind(f_chr);

		fread(seq_buffer, sizeof(char), length, f_chr);

		seq_buffer[length] = 0;
	} // whole chromosome reading check.

	// If the requested strand is on negative strand, do reverse complementing.
	if(strand == '-')
	{
		// Replace the sequence buffer with its reverse complement.
		char* reverse_complement_seq = get_reverse_complement(seq_buffer, 0, t_string::string_length(seq_buffer) - 1);
		delete [] seq_buffer;
		seq_buffer = reverse_complement_seq;
	}

	fclose(f_chr);

	if(upper_case)
	{
		t_string::to_upper(seq_buffer);
	}

	return(seq_buffer);
}

// Assembly:
subq $0x478, %rsp            # imm = 0x478
movl %r8d, 0x1c(%rsp)
movl %ecx, %eax
movl 0x1c(%rsp), %ecx
movl %eax, 0x20(%rsp)
movl %edx, %eax
movl 0x20(%rsp), %edx
movl %eax, 0x24(%rsp)
movq %rsi, %rax
movl 0x24(%rsp), %esi
movq %rax, 0x28(%rsp)
movq %rdi, %r8
movq 0x28(%rsp), %rdi
movb %r9b, %al
movq %r8, 0x468(%rsp)
movq %rdi, 0x460(%rsp)
movl %esi, 0x45c(%rsp)
movl %edx, 0x458(%rsp)
movb %cl, 0x457(%rsp)
andb $0x1, %al
movb %al, 0x456(%rsp)
leaq 0x60(%rsp), %rdi
movq 0x468(%rsp), %rdx
movq 0x460(%rsp), %rcx
leaq 0x15b0e(%rip), %rsi     # 0x52f8f
movb $0x0, %al
callq 0x2090
leaq 0x60(%rsp), %rdi
leaq 0x18e6c(%rip), %rsi     # 0x56300
callq 0x21d0
movq %rax, 0x58(%rsp)
cmpq $0x0, 0x58(%rsp)
jne 0x3d51a
leaq 0x60(%rsp), %rdi
movq 0x468(%rsp), %rdx
movq 0x460(%rsp), %rcx
leaq 0x15acd(%rip), %rsi     # 0x52f8f
movb $0x0, %al
callq 0x2090
leaq 0x60(%rsp), %rdi
leaq 0x18e2b(%rip), %rsi     # 0x56300
callq 0x21d0
movq %rax, 0x58(%rsp)
cmpq $0x0, 0x58(%rsp)
jne 0x3d518
movq 0x27af2(%rip), %rax     # 0x64fe0
movq (%rax), %rdi
movq 0x460(%rsp), %rdx
leaq 0x19236(%rip), %rsi     # 0x56736
movb $0x0, %al
callq 0x2250
movq $0x0, 0x470(%rsp)
jmp 0x3d704
jmp 0x3d51a
movl $0x0, 0x54(%rsp)
movq 0x58(%rsp), %rcx
leaq 0x54(%rsp), %rdi
movl $0x4, %esi
movl $0x1, %edx
callq 0x2270
movl 0x45c(%rsp), %eax
subl $0x1, %eax
cltq
addq $0x4, %rax
movl %eax, 0x50(%rsp)
movl 0x50(%rsp), %eax
movl 0x458(%rsp), %ecx
subl 0x45c(%rsp), %ecx
addl %ecx, %eax
movl %eax, 0x4c(%rsp)
movq $0x0, 0x40(%rsp)
movl 0x50(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x3d5fe
movl 0x458(%rsp), %eax
subl 0x45c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
addl $0x2, %eax
movslq %eax, %rdi
callq 0x2040
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movslq %eax, %rdx
shlq $0x0, %rdx
xorl %esi, %esi
callq 0x2110
movq 0x58(%rsp), %rdi
movslq 0x50(%rsp), %rsi
xorl %edx, %edx
callq 0x21b0
movq 0x40(%rsp), %rdi
movslq 0x3c(%rsp), %rdx
movq 0x58(%rsp), %rcx
movl $0x1, %esi
callq 0x2270
movq 0x40(%rsp), %rax
movslq 0x3c(%rsp), %rcx
movb $0x0, (%rax,%rcx)
jmp 0x3d67e
movq 0x58(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x2, %edx
callq 0x21b0
movq 0x58(%rsp), %rdi
callq 0x2030
movl %eax, 0x38(%rsp)
movl 0x38(%rsp), %eax
addl $0x2, %eax
movslq %eax, %rdi
callq 0x2040
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
movl 0x38(%rsp), %eax
addl $0x1, %eax
movslq %eax, %rdx
shlq $0x0, %rdx
xorl %esi, %esi
callq 0x2110
movq 0x58(%rsp), %rdi
callq 0x2060
movq 0x40(%rsp), %rdi
movslq 0x38(%rsp), %rdx
movq 0x58(%rsp), %rcx
movl $0x1, %esi
callq 0x2270
movq 0x40(%rsp), %rax
movslq 0x38(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movsbl 0x457(%rsp), %eax
cmpl $0x2d, %eax
jne 0x3d6d9
movq 0x40(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x40(%rsp), %rdi
callq 0x47640
movq 0x8(%rsp), %rdi
movl %eax, %edx
subl $0x1, %edx
xorl %esi, %esi
callq 0x3d720
movq %rax, 0x30(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x3d6cf
movq 0x10(%rsp), %rdi
callq 0x2220
movq 0x30(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x58(%rsp), %rdi
callq 0x2180
testb $0x1, 0x456(%rsp)
je 0x3d6f7
movq 0x40(%rsp), %rdi
callq 0x4b170
movq 0x40(%rsp), %rax
movq %rax, 0x470(%rsp)
movq 0x470(%rsp), %rax
addq $0x478, %rsp            # imm = 0x478
retq
nopw %cs:(%rax,%rax)