// File: zeeev[P]DASVC/bamtools/src/utils/bamtools_fasta.cpp
// Function: BamTools::Fasta::FastaPrivate::GetBase(int const&, int const&, char&)
bool Fasta::FastaPrivate::GetBase(const int& refId, const int& position, char& base) {
  
    // make sure FASTA file is open
    if ( !IsOpen ) {
        cerr << "FASTA error : file not open for reading" << endl;
        return false;
    }
  
    // use index if available
    if ( HasIndex && !Index.empty() ) {
        
        // validate reference id 
        if ( (refId < 0) || (refId >= (int)Index.size()) ) {
            cerr << "FASTA error: invalid refId specified: " << refId << endl;
            return false;
        }
        
        // retrieve reference index data
        const FastaIndexData& referenceData = Index.at(refId);
        
        // validate position 
        if ( (position < 0) || (position > referenceData.Length) ) {
            cerr << "FASTA error: invalid position specified: " << position << endl;
            return false;
        }

        // calculate seek position & attempt jump
        const int64_t lines = position / referenceData.LineLength;
        const int64_t lineOffset = position % referenceData.LineLength;
        const int64_t seekTo = referenceData.Offset + (lines*referenceData.ByteLength) + lineOffset;
        if ( fseek64(Stream, seekTo, SEEK_SET) != 0 ) {
            cerr << "FASTA error : could not seek in file" << endl;
            return false;
        }
        
        // set base & return success
        base = getc(Stream);
        return true;
    }
    
    // else plow through sequentially
    else {
      
        // rewind FASTA file
        if ( !Rewind() ) {
            cerr << "FASTA error : could not rewind FASTA file" << endl;
            return false;
        }
        
        // iterate through fasta entries
        int currentId = 0;
        string header = "";
        string sequence = "";
        
        // get first entry
        GetNextHeader(header);
        GetNextSequence(sequence);
        
        while ( currentId != refId ) {
            GetNextHeader(header);
            GetNextSequence(sequence);
            ++currentId;
        }
        
        // get desired base from sequence 
        // TODO: error reporting on invalid position
        if ( currentId == refId && (sequence.length() >= (size_t)position) ) {          
            base = sequence.at(position);
            return true;
        }
      
        // could not get sequence
        return false;
    }
 
    // return success
    return true;
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xd8(%rsp)
movq %rsi, 0xd0(%rsp)
movq %rdx, 0xc8(%rsp)
movq %rcx, 0xc0(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0x30(%rsp)
testb $0x1, 0x8(%rax)
jne 0x10b039
movq 0x59fcf(%rip), %rdi     # 0x164fe0
leaq 0x28e4d(%rip), %rsi     # 0x133e65
callq 0x86700
movq %rax, %rdi
movq 0x59f49(%rip), %rsi     # 0x164f70
callq 0x86770
movb $0x0, 0xe7(%rsp)
jmp 0x10b473
movq 0x30(%rsp), %rax
testb $0x1, 0x18(%rax)
je 0x10b242
movq 0x30(%rsp), %rdi
addq $0x20, %rdi
callq 0x10c340
testb $0x1, %al
jne 0x10b242
movq 0xd0(%rsp), %rax
cmpl $0x0, (%rax)
jl 0x10b092
movq 0x30(%rsp), %rdi
movq 0xd0(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x2c(%rsp)
addq $0x20, %rdi
callq 0x10c390
movq %rax, %rcx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jl 0x10b0d3
movq 0x59f47(%rip), %rdi     # 0x164fe0
leaq 0x28ded(%rip), %rsi     # 0x133e8d
callq 0x86700
movq %rax, %rdi
movq 0xd0(%rsp), %rax
movl (%rax), %esi
callq 0x86d40
movq %rax, %rdi
movq 0x59eaf(%rip), %rsi     # 0x164f70
callq 0x86770
movb $0x0, 0xe7(%rsp)
jmp 0x10b473
movq 0x30(%rsp), %rdi
addq $0x20, %rdi
movq 0xd0(%rsp), %rax
movslq (%rax), %rsi
callq 0x10c3b0
movq %rax, 0xb8(%rsp)
movq 0xc8(%rsp), %rax
cmpl $0x0, (%rax)
jl 0x10b118
movq 0xc8(%rsp), %rax
movl (%rax), %eax
movq 0xb8(%rsp), %rcx
cmpl 0x20(%rcx), %eax
jle 0x10b159
movq 0x59ec1(%rip), %rdi     # 0x164fe0
leaq 0x28d8e(%rip), %rsi     # 0x133eb4
callq 0x86700
movq %rax, %rdi
movq 0xc8(%rsp), %rax
movl (%rax), %esi
callq 0x86d40
movq %rax, %rdi
movq 0x59e29(%rip), %rsi     # 0x164f70
callq 0x86770
movb $0x0, 0xe7(%rsp)
jmp 0x10b473
movq 0xc8(%rsp), %rax
movl (%rax), %eax
movq 0xb8(%rsp), %rcx
cltd
idivl 0x30(%rcx)
cltq
movq %rax, 0xb0(%rsp)
movq 0xc8(%rsp), %rax
movl (%rax), %eax
movq 0xb8(%rsp), %rcx
cltd
idivl 0x30(%rcx)
movq 0x30(%rsp), %rax
movslq %edx, %rcx
movq %rcx, 0xa8(%rsp)
movq 0xb8(%rsp), %rcx
movq 0x28(%rcx), %rcx
movq 0xb0(%rsp), %rdx
movq 0xb8(%rsp), %rsi
movslq 0x34(%rsi), %rsi
imulq %rsi, %rdx
addq %rdx, %rcx
addq 0xa8(%rsp), %rcx
movq %rcx, 0xa0(%rsp)
movq (%rax), %rdi
movq 0xa0(%rsp), %rsi
xorl %edx, %edx
callq 0x86c60
cmpl $0x0, %eax
je 0x10b21c
movq 0x59dec(%rip), %rdi     # 0x164fe0
leaq 0x28ce3(%rip), %rsi     # 0x133ede
callq 0x86700
movq %rax, %rdi
movq 0x59d66(%rip), %rsi     # 0x164f70
callq 0x86770
movb $0x0, 0xe7(%rsp)
jmp 0x10b473
movq 0x30(%rsp), %rax
movq (%rax), %rdi
callq 0x86220
movb %al, %cl
movq 0xc0(%rsp), %rax
movb %cl, (%rax)
movb $0x1, 0xe7(%rsp)
jmp 0x10b473
movq 0x30(%rsp), %rdi
callq 0x10a420
testb $0x1, %al
jne 0x10b27f
movq 0x59d89(%rip), %rdi     # 0x164fe0
leaq 0x28aed(%rip), %rsi     # 0x133d4b
callq 0x86700
movq %rax, %rdi
movq 0x59d03(%rip), %rsi     # 0x164f70
callq 0x86770
movb $0x0, 0xe7(%rsp)
jmp 0x10b473
movl $0x0, 0x9c(%rsp)
leaq 0x77(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x86da0
movq 0x20(%rsp), %rdx
leaq 0x299ce(%rip), %rsi     # 0x134c73
leaq 0x78(%rsp), %rdi
callq 0x86a00
jmp 0x10b2b1
leaq 0x77(%rsp), %rdi
callq 0x867b0
leaq 0x3f(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x86da0
movq 0x18(%rsp), %rdx
leaq 0x2999d(%rip), %rsi     # 0x134c73
leaq 0x40(%rsp), %rdi
callq 0x86a00
jmp 0x10b2e2
leaq 0x3f(%rsp), %rdi
callq 0x867b0
movq 0x30(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x10a470
jmp 0x10b2fd
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x10a970
jmp 0x10b30e
jmp 0x10b310
movl 0x9c(%rsp), %eax
movq 0xd0(%rsp), %rcx
cmpl (%rcx), %eax
je 0x10b3b3
movq 0x30(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x10a470
jmp 0x10b338
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x10a970
jmp 0x10b349
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x10b310
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x68(%rsp)
movl %eax, 0x64(%rsp)
leaq 0x77(%rsp), %rdi
callq 0x867b0
jmp 0x10b484
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x68(%rsp)
movl %eax, 0x64(%rsp)
leaq 0x3f(%rsp), %rdi
callq 0x867b0
jmp 0x10b465
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x68(%rsp)
movl %eax, 0x64(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x86f68
jmp 0x10b463
movl 0x9c(%rsp), %eax
movq 0xd0(%rsp), %rcx
cmpl (%rcx), %eax
jne 0x10b42b
leaq 0x40(%rsp), %rdi
callq 0x86ac0
movq %rax, 0x10(%rsp)
jmp 0x10b3d7
movq 0x10(%rsp), %rax
movq 0xc8(%rsp), %rcx
movslq (%rcx), %rcx
cmpq %rcx, %rax
jb 0x10b42b
movq 0xc8(%rsp), %rax
movslq (%rax), %rsi
leaq 0x40(%rsp), %rdi
callq 0x86ee0
movq %rax, 0x8(%rsp)
jmp 0x10b408
movq 0x8(%rsp), %rax
movb (%rax), %cl
movq 0xc0(%rsp), %rax
movb %cl, (%rax)
movb $0x1, 0xe7(%rsp)
movl $0x1, 0x38(%rsp)
jmp 0x10b43b
movb $0x0, 0xe7(%rsp)
movl $0x1, 0x38(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x86f68
jmp 0x10b447
leaq 0x78(%rsp), %rdi
callq 0x86f68
jmp 0x10b473
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x68(%rsp)
movl %eax, 0x64(%rsp)
jmp 0x10b465
jmp 0x10b465
leaq 0x78(%rsp), %rdi
callq 0x86f68
jmp 0x10b471
jmp 0x10b484
movb 0xe7(%rsp), %al
andb $0x1, %al
addq $0xe8, %rsp
retq
movq 0x68(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopw %cs:(%rax,%rax)