// File: zeeev[P]DASVC/bamtools/src/api/internal/index/BamToolsIndex_p.cpp
// Function: BamTools::Internal::BamToolsIndex::Create()
bool BamToolsIndex::Create(void) {

    // skip if BamReader is invalid or not open
    if ( m_reader == 0 || !m_reader->IsOpen() ) {
        SetErrorString("BamToolsIndex::Create", "could not create index: reader is not open");
        return false;
    }

    // rewind BamReader
    if ( !m_reader->Rewind() ) {
        const string readerError = m_reader->GetErrorString();
        const string message = "could not create index: \n\t" + readerError;
        SetErrorString("BamToolsIndex::Create", message);
        return false;
    }

    try {
        // open new index file (read & write)
        const string indexFilename = m_reader->Filename() + Extension();
        OpenFile(indexFilename, IBamIODevice::ReadWrite);

        // initialize BtiFileSummary with number of references
        const int& numReferences = m_reader->GetReferenceCount();
        InitializeFileSummary(numReferences);

        // intialize output file header
        WriteHeader();

        // index building markers
        uint32_t currentBlockCount      = 0;
        int64_t currentAlignmentOffset  = m_reader->Tell();
        int32_t blockRefId              = -1;
        int32_t blockMaxEndPosition     = -1;
        int64_t blockStartOffset        = currentAlignmentOffset;
        int32_t blockStartPosition      = -1;

        // plow through alignments, storing index entries
        BamAlignment al;
        BtiReferenceEntry refEntry;
        while ( m_reader->LoadNextAlignment(al) ) {

            // if moved to new reference
            if ( al.RefID != blockRefId ) {

                // if first pass, check:
                if ( currentBlockCount == 0 ) {

                    // write any empty references up to (but not including) al.RefID
                    for ( int i = 0; i < al.RefID; ++i )
                        WriteReferenceEntry( BtiReferenceEntry(i) );
                }

                // not first pass:
                else {

                    // store previous BTI block data in reference entry
                    const BtiBlock block(blockMaxEndPosition, blockStartOffset, blockStartPosition);
                    refEntry.Blocks.push_back(block);

                    // write reference entry, then clear
                    WriteReferenceEntry(refEntry);
                    ClearReferenceEntry(refEntry);

                    // write any empty references between (but not including)
                    // the last blockRefID and current al.RefID
                    for ( int i = blockRefId+1; i < al.RefID; ++i )
                        WriteReferenceEntry( BtiReferenceEntry(i) );

                    // reset block count
                    currentBlockCount = 0;
                }

                // set ID for new reference entry
                refEntry.ID = al.RefID;
            }

            // if beginning of block, update counters
            if ( currentBlockCount == 0 ) {
                blockRefId          = al.RefID;
                blockStartOffset    = currentAlignmentOffset;
                blockStartPosition  = al.Position;
                blockMaxEndPosition = al.GetEndPosition();
            }

            // increment block counter
            ++currentBlockCount;

            // check end position
            const int32_t alignmentEndPosition = al.GetEndPosition();
            if ( alignmentEndPosition > blockMaxEndPosition )
                blockMaxEndPosition = alignmentEndPosition;

            // if block is full, get offset for next block, reset currentBlockCount
            if ( currentBlockCount == m_blockSize ) {

                // store previous block data in reference entry
                const BtiBlock block(blockMaxEndPosition, blockStartOffset, blockStartPosition);
                refEntry.Blocks.push_back(block);

                // update markers
                blockStartOffset  = m_reader->Tell();
                currentBlockCount = 0;
            }

            // not the best name, but for the next iteration, this value will be the offset of the
            // *current* alignment. this is necessary because we won't know if this next alignment
            // is on a new reference until we actually read it
            currentAlignmentOffset = m_reader->Tell();
        }

        // after finishing alignments, if any data was read, check:
        if ( blockRefId >= 0 ) {

            // store last BTI block data in reference entry
            const BtiBlock block(blockMaxEndPosition, blockStartOffset, blockStartPosition);
            refEntry.Blocks.push_back(block);

            // write last reference entry, then clear
            WriteReferenceEntry(refEntry);
            ClearReferenceEntry(refEntry);

            // then write any empty references remaining at end of file
            for ( int i = blockRefId+1; i < numReferences; ++i )
                WriteReferenceEntry( BtiReferenceEntry(i) );
        }

    } catch ( BamException& e ) {
        m_errorString = e.what();
        return false;
    }

    // rewind BamReader
    if ( !m_reader->Rewind() ) {
        const string readerError = m_reader->GetErrorString();
        const string message = "could not create index: \n\t" + readerError;
        SetErrorString("BamToolsIndex::Create", message);
        return false;
    }

    // return success
    return true;
}

// Assembly:
subq $0x488, %rsp            # imm = 0x488
movq %rdi, 0x478(%rsp)
movq 0x478(%rsp), %rax
movq %rax, 0x68(%rsp)
cmpq $0x0, 0x8(%rax)
je 0xc0e39
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x77980
testb $0x1, %al
jne 0xc0f75
leaq 0x457(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x7b5f0
movq 0x60(%rsp), %rdx
leaq 0x2aa7a(%rip), %rsi     # 0xeb8d1
leaq 0x458(%rsp), %rdi
callq 0x78e70
jmp 0xc0e66
leaq 0x41f(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x7b5f0
movq 0x58(%rsp), %rdx
leaq 0x2a32e(%rip), %rsi     # 0xeb1b2
leaq 0x420(%rsp), %rdi
callq 0x78e70
jmp 0xc0e93
movq 0x68(%rsp), %rdi
leaq 0x458(%rsp), %rsi
leaq 0x420(%rsp), %rdx
callq 0x71d90
jmp 0xc0eaf
leaq 0x420(%rsp), %rdi
callq 0x7cce8
jmp 0xc0ebe
leaq 0x41f(%rsp), %rdi
callq 0x76f80
leaq 0x458(%rsp), %rdi
callq 0x7cce8
jmp 0xc0eda
leaq 0x457(%rsp), %rdi
callq 0x76f80
movb $0x0, 0x487(%rsp)
jmp 0xc1966
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc0f63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc0f45
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0x420(%rsp), %rdi
callq 0x7cce8
jmp 0xc0f43
jmp 0xc0f45
leaq 0x41f(%rsp), %rdi
callq 0x76f80
leaq 0x458(%rsp), %rdi
callq 0x7cce8
jmp 0xc0f61
jmp 0xc0f63
leaq 0x457(%rsp), %rdi
callq 0x76f80
jmp 0xc1977
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x7b0d0
testb $0x1, %al
jne 0xc10d2
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rsi
leaq 0x3f8(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x7bbf0
movq 0x50(%rsp), %rdx
leaq 0x29b57(%rip), %rsi     # 0xeab09
leaq 0x3d8(%rsp), %rdi
callq 0x75e70
jmp 0xc0fc1
leaq 0x3b7(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x7b5f0
movq 0x48(%rsp), %rdx
leaq 0x2a8f2(%rip), %rsi     # 0xeb8d1
leaq 0x3b8(%rsp), %rdi
callq 0x78e70
jmp 0xc0fee
movq 0x68(%rsp), %rdi
leaq 0x3b8(%rsp), %rsi
leaq 0x3d8(%rsp), %rdx
callq 0x71d90
jmp 0xc100a
leaq 0x3b8(%rsp), %rdi
callq 0x7cce8
jmp 0xc1019
leaq 0x3b7(%rsp), %rdi
callq 0x76f80
movb $0x0, 0x487(%rsp)
leaq 0x3d8(%rsp), %rdi
callq 0x7cce8
jmp 0xc10aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc10be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc108e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0x3b8(%rsp), %rdi
callq 0x7cce8
jmp 0xc108c
jmp 0xc108e
leaq 0x3b7(%rsp), %rdi
callq 0x76f80
leaq 0x3d8(%rsp), %rdi
callq 0x7cce8
jmp 0xc10bc
leaq 0x3f8(%rsp), %rdi
callq 0x7cce8
jmp 0xc1966
jmp 0xc10be
leaq 0x3f8(%rsp), %rdi
callq 0x7cce8
jmp 0xc10cd
jmp 0xc1977
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rsi
leaq 0x370(%rsp), %rdi
callq 0x78400
jmp 0xc10ea
leaq 0x350(%rsp), %rdi
callq 0x7a0e0
jmp 0xc10f9
leaq 0x390(%rsp), %rdi
leaq 0x370(%rsp), %rsi
leaq 0x350(%rsp), %rdx
callq 0x7c720
jmp 0xc1118
leaq 0x350(%rsp), %rdi
callq 0x7cce8
jmp 0xc1127
leaq 0x370(%rsp), %rdi
callq 0x7cce8
jmp 0xc1136
movq 0x68(%rsp), %rdi
leaq 0x390(%rsp), %rsi
movl $0x3, %edx
callq 0x74480
jmp 0xc114f
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x77160
movl %eax, 0x44(%rsp)
jmp 0xc1163
movq 0x68(%rsp), %rdi
movl 0x44(%rsp), %eax
movl %eax, 0x344(%rsp)
leaq 0x344(%rsp), %rax
movq %rax, 0x348(%rsp)
movq 0x348(%rsp), %rsi
callq 0x7b7e0
jmp 0xc1192
movq 0x68(%rsp), %rdi
callq 0x78f50
jmp 0xc119e
movq 0x68(%rsp), %rax
movl $0x0, 0x340(%rsp)
movq 0x8(%rax), %rdi
callq 0x739a0
movq %rax, 0x38(%rsp)
jmp 0xc11be
movq 0x38(%rsp), %rax
movq %rax, 0x338(%rsp)
movl $0xffffffff, 0x334(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x330(%rsp) # imm = 0xFFFFFFFF
movq 0x338(%rsp), %rax
movq %rax, 0x328(%rsp)
movl $0xffffffff, 0x324(%rsp) # imm = 0xFFFFFFFF
leaq 0x1c8(%rsp), %rdi
callq 0x72830
jmp 0xc120b
movl $0xffffffff, 0x1a4(%rsp) # imm = 0xFFFFFFFF
leaq 0x1a8(%rsp), %rdi
leaq 0x1a4(%rsp), %rsi
callq 0x78890
jmp 0xc122d
jmp 0xc122f
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x74860
movb %al, 0x37(%rsp)
jmp 0xc124b
movb 0x37(%rsp), %al
testb $0x1, %al
jne 0xc1258
jmp 0xc162a
movl 0x270(%rsp), %eax
cmpl 0x334(%rsp), %eax
je 0xc14df
cmpl $0x0, 0x340(%rsp)
jne 0xc13c8
movl $0x0, 0x1a0(%rsp)
movl 0x1a0(%rsp), %eax
cmpl 0x270(%rsp), %eax
jge 0xc13c3
leaq 0x180(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x78890
jmp 0xc12b0
movq 0x68(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x71fb0
jmp 0xc12c4
leaq 0x180(%rsp), %rdi
callq 0x79d10
jmp 0xc12d3
jmp 0xc12d5
movl 0x1a0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a0(%rsp)
jmp 0xc1285
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc179d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc133c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0x350(%rsp), %rdi
callq 0x7cce8
jmp 0xc133a
jmp 0xc133c
leaq 0x370(%rsp), %rdi
callq 0x7cce8
jmp 0xc134b
jmp 0xc179d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc178c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc177b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc176a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0x180(%rsp), %rdi
callq 0x79d10
jmp 0xc13be
jmp 0xc176a
jmp 0xc14d1
leaq 0x168(%rsp), %rdi
leaq 0x330(%rsp), %rsi
leaq 0x328(%rsp), %rdx
leaq 0x324(%rsp), %rcx
callq 0x79e50
jmp 0xc13ef
leaq 0x1b0(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x768c0
jmp 0xc1406
movq 0x68(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0x71fb0
jmp 0xc141a
movq 0x68(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0x7b280
jmp 0xc142e
movl 0x334(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x164(%rsp)
movl 0x164(%rsp), %eax
cmpl 0x270(%rsp), %eax
jge 0xc14c6
leaq 0x140(%rsp), %rdi
leaq 0x164(%rsp), %rsi
callq 0x78890
jmp 0xc1466
movq 0x68(%rsp), %rdi
leaq 0x140(%rsp), %rsi
callq 0x71fb0
jmp 0xc147a
leaq 0x140(%rsp), %rdi
callq 0x79d10
jmp 0xc1489
jmp 0xc148b
movl 0x164(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x164(%rsp)
jmp 0xc143f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x79d10
jmp 0xc14c1
jmp 0xc176a
movl $0x0, 0x340(%rsp)
movl 0x270(%rsp), %eax
movl %eax, 0x1a8(%rsp)
cmpl $0x0, 0x340(%rsp)
jne 0xc1537
movl 0x270(%rsp), %eax
movl %eax, 0x334(%rsp)
movq 0x338(%rsp), %rax
movq %rax, 0x328(%rsp)
movl 0x274(%rsp), %eax
movl %eax, 0x324(%rsp)
leaq 0x1c8(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x76240
movl %eax, 0x30(%rsp)
jmp 0xc152c
movl 0x30(%rsp), %eax
movl %eax, 0x330(%rsp)
movl 0x340(%rsp), %eax
incl %eax
movl %eax, 0x340(%rsp)
leaq 0x1c8(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x76240
movl %eax, 0x2c(%rsp)
jmp 0xc155e
movl 0x2c(%rsp), %eax
movl %eax, 0x13c(%rsp)
movl 0x13c(%rsp), %eax
cmpl 0x330(%rsp), %eax
jle 0xc1587
movl 0x13c(%rsp), %eax
movl %eax, 0x330(%rsp)
movq 0x68(%rsp), %rcx
movl 0x340(%rsp), %eax
cmpl 0x50(%rcx), %eax
jne 0xc1603
leaq 0x120(%rsp), %rdi
leaq 0x330(%rsp), %rsi
leaq 0x328(%rsp), %rdx
leaq 0x324(%rsp), %rcx
callq 0x79e50
jmp 0xc15bf
leaq 0x1b0(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x768c0
jmp 0xc15d6
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x739a0
movq %rax, 0x20(%rsp)
jmp 0xc15eb
movq 0x20(%rsp), %rax
movq %rax, 0x328(%rsp)
movl $0x0, 0x340(%rsp)
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x739a0
movq %rax, 0x18(%rsp)
jmp 0xc1618
movq 0x18(%rsp), %rax
movq %rax, 0x338(%rsp)
jmp 0xc122f
cmpl $0x0, 0x334(%rsp)
jl 0xc1738
leaq 0x108(%rsp), %rdi
leaq 0x330(%rsp), %rsi
leaq 0x328(%rsp), %rdx
leaq 0x324(%rsp), %rcx
callq 0x79e50
jmp 0xc165f
leaq 0x1b0(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x768c0
jmp 0xc1676
movq 0x68(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0x71fb0
jmp 0xc168a
movq 0x68(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0x7b280
jmp 0xc169e
movl 0x334(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
movl 0x104(%rsp), %eax
movq 0x348(%rsp), %rcx
cmpl (%rcx), %eax
jge 0xc1736
leaq 0xe0(%rsp), %rdi
leaq 0x104(%rsp), %rsi
callq 0x78890
jmp 0xc16d9
movq 0x68(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x71fb0
jmp 0xc16ed
leaq 0xe0(%rsp), %rdi
callq 0x79d10
jmp 0xc16fc
jmp 0xc16fe
movl 0x104(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
jmp 0xc16af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x79d10
jmp 0xc1734
jmp 0xc176a
jmp 0xc1738
leaq 0x1a8(%rsp), %rdi
callq 0x79d10
jmp 0xc1747
leaq 0x1c8(%rsp), %rdi
callq 0x7a0d0
jmp 0xc1756
leaq 0x390(%rsp), %rdi
callq 0x7cce8
jmp 0xc1765
jmp 0xc181c
leaq 0x1a8(%rsp), %rdi
callq 0x79d10
jmp 0xc1779
jmp 0xc177b
leaq 0x1c8(%rsp), %rdi
callq 0x7a0d0
jmp 0xc178a
jmp 0xc178c
leaq 0x390(%rsp), %rdi
callq 0x7cce8
jmp 0xc179b
jmp 0xc179d
movl 0x444(%rsp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0xc1977
movq 0x448(%rsp), %rdi
callq 0x72fc0
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq 0x68(%rsp), %rdi
movq %rax, %rsi
addq $0x10, %rdi
callq 0x78d10
jmp 0xc17ea
movb $0x0, 0x487(%rsp)
callq 0x7a790
jmp 0xc1966
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
callq 0x7a790
jmp 0xc1817
jmp 0xc1977
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x7b0d0
testb $0x1, %al
jne 0xc195e
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rsi
leaq 0xb8(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x7bbf0
movq 0x10(%rsp), %rdx
leaq 0x292b0(%rip), %rsi     # 0xeab09
leaq 0x98(%rsp), %rdi
callq 0x75e70
jmp 0xc1868
leaq 0x77(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x7b5f0
movq 0x8(%rsp), %rdx
leaq 0x2a04e(%rip), %rsi     # 0xeb8d1
leaq 0x78(%rsp), %rdi
callq 0x78e70
jmp 0xc188f
movq 0x68(%rsp), %rdi
leaq 0x78(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0x71d90
jmp 0xc18a8
leaq 0x78(%rsp), %rdi
callq 0x7cce8
jmp 0xc18b4
leaq 0x77(%rsp), %rdi
callq 0x76f80
movb $0x0, 0x487(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x7cce8
jmp 0xc193c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc194d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
jmp 0xc1923
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x448(%rsp)
movl %eax, 0x444(%rsp)
leaq 0x78(%rsp), %rdi
callq 0x7cce8
jmp 0xc1921
jmp 0xc1923
leaq 0x77(%rsp), %rdi
callq 0x76f80
leaq 0x98(%rsp), %rdi
callq 0x7cce8
jmp 0xc194b
leaq 0xb8(%rsp), %rdi
callq 0x7cce8
jmp 0xc1966
jmp 0xc194d
leaq 0xb8(%rsp), %rdi
callq 0x7cce8
jmp 0xc195c
jmp 0xc1977
movb $0x1, 0x487(%rsp)
movb 0x487(%rsp), %al
andb $0x1, %al
addq $0x488, %rsp            # imm = 0x488
retq
movq 0x448(%rsp), %rdi
callq 0x7b550
movq %rax, %rdi
callq 0x88ef0
nopl (%rax)