// File: zeeev[P]DASVC/bamtools/src/toolkit/bamtools_random.cpp
// Function: BamTools::RandomTool::RandomToolPrivate::Run()
bool RandomTool::RandomToolPrivate::Run(void) {

    // set to default stdin if no input files provided
    if ( !m_settings->HasInput && !m_settings->HasInputFilelist )
        m_settings->InputFiles.push_back(Options::StandardIn());

    // add files in the filelist to the input file list
    if ( m_settings->HasInputFilelist ) {

        ifstream filelist(m_settings->InputFilelist.c_str(), ios::in);
        if ( !filelist.is_open() ) {
            cerr << "bamtools random ERROR: could not open input BAM file list... Aborting." << endl;
            return false;
        }

        string line;
        while ( getline(filelist, line) )
            m_settings->InputFiles.push_back(line);
    }

    // open our reader
    BamMultiReader reader;
    if ( !reader.Open(m_settings->InputFiles) ) {
        cerr << "bamtools random ERROR: could not open input BAM file(s)... Aborting." << endl;
        return false;
    }

    // look up index files for all BAM files
    reader.LocateIndexes();

    // make sure index data is available
    if ( !reader.HasIndexes() ) {
        cerr << "bamtools random ERROR: could not load index data for all input BAM file(s)... Aborting." << endl;
        reader.Close();
        return false;
    }

    // get BamReader metadata
    const string headerText = reader.GetHeaderText();
    const RefVector references = reader.GetReferenceData();
    if ( references.empty() ) {
        cerr << "bamtools random ERROR: no reference data available... Aborting." << endl;
        reader.Close();
        return false;
    }

    // determine compression mode for BamWriter
    bool writeUncompressed = ( m_settings->OutputFilename == Options::StandardOut() &&
                              !m_settings->IsForceCompression );
    BamWriter::CompressionMode compressionMode = BamWriter::Compressed;
    if ( writeUncompressed ) compressionMode = BamWriter::Uncompressed;

    // open BamWriter
    BamWriter writer;
    writer.SetCompressionMode(compressionMode);
    if ( !writer.Open(m_settings->OutputFilename, headerText, references) ) {
        cerr << "bamtools random ERROR: could not open " << m_settings->OutputFilename
             << " for writing... Aborting." << endl;
        reader.Close();
        return false;
    }

    // if user specified a REGION constraint, attempt to parse REGION string
    BamRegion region;
    if ( m_settings->HasRegion && !Utilities::ParseRegionString(m_settings->Region, reader, region) ) {
        cerr << "bamtools random ERROR: could not parse REGION: " << m_settings->Region << endl;
        cerr << "Check that REGION is in valid format (see documentation) and that the coordinates are valid"
             << endl;
        reader.Close();
        writer.Close();
        return false;
    }

    // seed our random number generator
    if ( m_settings->HasRandomNumberSeed )
        srand( m_settings->RandomNumberSeed );
    else
        srand( time(NULL) );

    // grab random alignments
    BamAlignment al;
    unsigned int i = 0;
    while ( i < m_settings->AlignmentCount ) {

        int randomRefId    = 0;
        int randomPosition = 0;

        // use REGION constraints to select random refId & position
        if ( m_settings->HasRegion ) {

            // select a random refId
            randomRefId = getRandomInt(region.LeftRefID, region.RightRefID);

            // select a random position based on randomRefId
            const int lowerBoundPosition = ( (randomRefId == region.LeftRefID)
                                             ? region.LeftPosition
                                             : 0 );
            const int upperBoundPosition = ( (randomRefId == region.RightRefID)
                                             ? region.RightPosition
                                             : (references.at(randomRefId).RefLength - 1) );
            randomPosition = getRandomInt(lowerBoundPosition, upperBoundPosition);
        }

        // otherwise select from all possible random refId & position
        else {

            // select random refId
            randomRefId = getRandomInt(0, (int)references.size() - 1);

            // select random position based on randomRefId
            const int lowerBoundPosition = 0;
            const int upperBoundPosition = references.at(randomRefId).RefLength - 1;
            randomPosition = getRandomInt(lowerBoundPosition, upperBoundPosition);
        }

        // if jump & read successful, save first alignment that overlaps random refId & position
        if ( reader.Jump(randomRefId, randomPosition) ) {
            while ( reader.GetNextAlignmentCore(al) ) {
                if ( al.RefID == randomRefId && al.Position >= randomPosition ) {
                    writer.SaveAlignment(al);
                    ++i;
                    break;
                }
            }
        }
    }

    // cleanup & exit
    reader.Close();
    writer.Close();
    return true;
}

// Assembly:
subq $0x528, %rsp            # imm = 0x528
movq %rdi, 0x518(%rsp)
movq 0x518(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq (%rax), %rax
testb $0x1, 0x1(%rax)
jne 0xc4b45
movq 0xe0(%rsp), %rax
movq (%rax), %rax
testb $0x1, 0x2(%rax)
jne 0xc4b45
movq 0xe0(%rsp), %rax
movq (%rax), %rax
addq $0x10, %rax
movq %rax, 0xd8(%rsp)
callq 0x10f280
movq 0xd8(%rsp), %rdi
movq %rax, %rsi
callq 0x91220
movq 0xe0(%rsp), %rax
movq (%rax), %rax
testb $0x1, 0x2(%rax)
je 0xc4d05
movq 0xe0(%rsp), %rax
movq (%rax), %rdi
addq $0x28, %rdi
callq 0x86320
movq %rax, %rsi
leaq 0x310(%rsp), %rdi
movq %rdi, 0xc8(%rsp)
movl $0x8, %edx
callq 0x86e30
movq 0xc8(%rsp), %rdi
callq 0x86c10
movb %al, 0xd7(%rsp)
jmp 0xc4ba1
movb 0xd7(%rsp), %al
testb $0x1, %al
jne 0xc4c12
jmp 0xc4bae
movq 0xa042b(%rip), %rdi     # 0x164fe0
leaq 0x6b82c(%rip), %rsi     # 0x1303e8
callq 0x86700
movq %rax, 0xc0(%rsp)
jmp 0xc4bcb
movq 0xc0(%rsp), %rdi
movq 0xa0396(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc4be1
movb $0x0, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
jmp 0xc4cce
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0xc4cf1
leaq 0x2e0(%rsp), %rdi
callq 0x86a30
jmp 0xc4c21
jmp 0xc4c23
leaq 0x310(%rsp), %rdi
leaq 0x2e0(%rsp), %rsi
callq 0x86140
movq %rax, 0xb8(%rsp)
jmp 0xc4c42
movq 0xb8(%rsp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x86b60
movq %rax, 0xb0(%rsp)
jmp 0xc4c63
movq 0xb0(%rsp), %rax
cmpq $0x0, %rax
je 0xc4cb4
movq 0xe0(%rsp), %rax
movq (%rax), %rdi
addq $0x10, %rdi
leaq 0x2e0(%rsp), %rsi
callq 0x91220
jmp 0xc4c8f
jmp 0xc4c23
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
leaq 0x2e0(%rsp), %rdi
callq 0x86f68
jmp 0xc4cef
leaq 0x2e0(%rsp), %rdi
callq 0x86f68
jmp 0xc4cc3
movl $0x0, 0x300(%rsp)
leaq 0x310(%rsp), %rdi
callq 0x861c0
movl 0x300(%rsp), %eax
testl %eax, %eax
je 0xc4ced
jmp 0xc4ce8
jmp 0xc559e
jmp 0xc4d05
jmp 0xc4cf1
leaq 0x310(%rsp), %rdi
callq 0x861c0
jmp 0xc4d00
jmp 0xc55af
leaq 0x2d8(%rsp), %rdi
movq %rdi, 0xa0(%rsp)
callq 0x86db0
movq 0xe0(%rsp), %rax
movq 0xa0(%rsp), %rdi
movq (%rax), %rsi
addq $0x10, %rsi
callq 0x864a0
movb %al, 0xaf(%rsp)
jmp 0xc4d3f
movb 0xaf(%rsp), %al
testb $0x1, %al
jne 0xc4db0
jmp 0xc4d4c
movq 0xa028d(%rip), %rdi     # 0x164fe0
leaq 0x6b6d5(%rip), %rsi     # 0x13042f
callq 0x86700
movq %rax, 0x98(%rsp)
jmp 0xc4d69
movq 0x98(%rsp), %rdi
movq 0xa01f8(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc4d7f
movb $0x0, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
jmp 0xc557e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0xc558d
movl $0x1, 0x2d4(%rsp)
leaq 0x2d8(%rsp), %rdi
leaq 0x2d4(%rsp), %rsi
callq 0x86950
jmp 0xc4dd2
leaq 0x2d8(%rsp), %rdi
callq 0x864c0
movb %al, 0x97(%rsp)
jmp 0xc4de8
movb 0x97(%rsp), %al
testb $0x1, %al
jne 0xc4e4f
jmp 0xc4df5
movq 0xa01e4(%rip), %rdi     # 0x164fe0
leaq 0x6b671(%rip), %rsi     # 0x130474
callq 0x86700
movq %rax, 0x88(%rsp)
jmp 0xc4e12
movq 0x88(%rsp), %rdi
movq 0xa014f(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc4e28
leaq 0x2d8(%rsp), %rdi
callq 0x861e0
jmp 0xc4e37
movb $0x0, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
jmp 0xc557e
leaq 0x2b0(%rsp), %rdi
leaq 0x2d8(%rsp), %rsi
callq 0x865f0
jmp 0xc4e66
leaq 0x298(%rsp), %rdi
leaq 0x2d8(%rsp), %rsi
callq 0x862c0
jmp 0xc4e7d
leaq 0x298(%rsp), %rdi
callq 0xc6c70
movb %al, 0x87(%rsp)
jmp 0xc4e93
movb 0x87(%rsp), %al
testb $0x1, %al
jne 0xc4ea3
jmp 0xc4f29
movq 0xa0136(%rip), %rdi     # 0x164fe0
leaq 0x6b61b(%rip), %rsi     # 0x1304cc
callq 0x86700
movq %rax, 0x78(%rsp)
jmp 0xc4ebd
movq 0x78(%rsp), %rdi
movq 0xa00a7(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc4ed0
leaq 0x2d8(%rsp), %rdi
callq 0x861e0
jmp 0xc4edf
movb $0x0, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
jmp 0xc553c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0xc556d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0xc555a
movq 0xe0(%rsp), %rax
movq (%rax), %rax
addq $0x48, %rax
movq %rax, 0x68(%rsp)
callq 0x10f290
movq %rax, 0x70(%rsp)
jmp 0xc4f49
movq 0x70(%rsp), %rsi
movq 0x68(%rsp), %rdi
callq 0x91630
movb %al, 0x67(%rsp)
jmp 0xc4f5e
movb 0x67(%rsp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, 0x66(%rsp)
jne 0xc4f6f
jmp 0xc4f83
movq 0xe0(%rsp), %rax
movq (%rax), %rax
movb 0x6(%rax), %al
xorb $-0x1, %al
movb %al, 0x66(%rsp)
movb 0x66(%rsp), %al
andb $0x1, %al
movb %al, 0x297(%rsp)
movl $0x0, 0x290(%rsp)
testb $0x1, 0x297(%rsp)
je 0xc4fb0
movl $0x1, 0x290(%rsp)
leaq 0x288(%rsp), %rdi
callq 0x863f0
jmp 0xc4fbf
leaq 0x288(%rsp), %rdi
leaq 0x290(%rsp), %rsi
callq 0x86280
jmp 0xc4fd6
movq 0xe0(%rsp), %rax
movq (%rax), %rsi
addq $0x48, %rsi
leaq 0x288(%rsp), %rdi
leaq 0x2b0(%rsp), %rdx
leaq 0x298(%rsp), %rcx
callq 0x86bd0
movb %al, 0x65(%rsp)
jmp 0xc5008
movb 0x65(%rsp), %al
testb $0x1, %al
jne 0xc50bb
jmp 0xc5016
movq 0x9ffc3(%rip), %rdi     # 0x164fe0
leaq 0x6b4e8(%rip), %rsi     # 0x13050c
callq 0x86700
movq %rax, 0x58(%rsp)
jmp 0xc5030
movq 0x58(%rsp), %rdi
movq 0xe0(%rsp), %rax
movq (%rax), %rsi
addq $0x48, %rsi
callq 0x86640
movq %rax, 0x50(%rsp)
jmp 0xc5050
movq 0x50(%rsp), %rdi
leaq 0x6b4d7(%rip), %rsi     # 0x130533
callq 0x86700
movq %rax, 0x48(%rsp)
jmp 0xc5068
movq 0x48(%rsp), %rdi
movq 0x9fefc(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc507b
leaq 0x2d8(%rsp), %rdi
callq 0x861e0
jmp 0xc508a
movb $0x0, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
jmp 0xc551a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0xc552b
movl $0xffffffff, 0x274(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x270(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x26c(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x268(%rsp) # imm = 0xFFFFFFFF
leaq 0x278(%rsp), %rdi
leaq 0x274(%rsp), %rsi
leaq 0x270(%rsp), %rdx
leaq 0x26c(%rsp), %rcx
leaq 0x268(%rsp), %r8
callq 0x915e0
jmp 0xc5116
movq 0xe0(%rsp), %rax
movq (%rax), %rax
testb $0x1, 0x5(%rax)
je 0xc5213
movq 0xe0(%rsp), %rax
movq (%rax), %rdi
addq $0x70, %rdi
leaq 0x2d8(%rsp), %rsi
leaq 0x278(%rsp), %rdx
callq 0x115500
movb %al, 0x47(%rsp)
jmp 0xc5155
movb 0x47(%rsp), %al
testb $0x1, %al
jne 0xc5213
jmp 0xc5163
movq 0x9fe76(%rip), %rdi     # 0x164fe0
leaq 0x6b3dc(%rip), %rsi     # 0x13054d
callq 0x86700
movq %rax, 0x38(%rsp)
jmp 0xc517d
movq 0x38(%rsp), %rdi
movq 0xe0(%rsp), %rax
movq (%rax), %rsi
addq $0x70, %rsi
callq 0x86640
movq %rax, 0x30(%rsp)
jmp 0xc519d
movq 0x30(%rsp), %rdi
movq 0x9fdc7(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc51b0
movq 0x9fe29(%rip), %rdi     # 0x164fe0
leaq 0x69196(%rip), %rsi     # 0x12e354
callq 0x86700
movq %rax, 0x28(%rsp)
jmp 0xc51ca
movq 0x28(%rsp), %rdi
movq 0x9fd9a(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0xc51dd
leaq 0x2d8(%rsp), %rdi
callq 0x861e0
jmp 0xc51ec
leaq 0x288(%rsp), %rdi
callq 0x86410
jmp 0xc51fb
movb $0x0, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
jmp 0xc551a
movq 0xe0(%rsp), %rax
movq (%rax), %rax
testb $0x1, 0x4(%rax)
je 0xc5239
movq 0xe0(%rsp), %rax
movq (%rax), %rax
movl 0x68(%rax), %edi
callq 0x866d0
jmp 0xc5249
xorl %eax, %eax
movl %eax, %edi
callq 0x86670
movl %eax, %edi
callq 0x866d0
leaq 0x110(%rsp), %rdi
callq 0x86260
jmp 0xc5258
movl $0x0, 0x10c(%rsp)
movq 0xe0(%rsp), %rcx
movl 0x10c(%rsp), %eax
movq (%rcx), %rcx
cmpl 0x8(%rcx), %eax
jae 0xc54d6
movq 0xe0(%rsp), %rax
movl $0x0, 0x108(%rsp)
movl $0x0, 0x104(%rsp)
movq (%rax), %rax
testb $0x1, 0x5(%rax)
je 0xc5393
leaq 0x278(%rsp), %rdi
leaq 0x278(%rsp), %rsi
addq $0x8, %rsi
callq 0xc4a70
movl %eax, 0x108(%rsp)
movl 0x108(%rsp), %eax
cmpl 0x278(%rsp), %eax
jne 0xc52e6
movl 0x27c(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0xc52ee
xorl %eax, %eax
movl %eax, 0x24(%rsp)
jmp 0xc52ee
movl 0x24(%rsp), %eax
movl %eax, 0x100(%rsp)
movl 0x108(%rsp), %eax
cmpl 0x280(%rsp), %eax
jne 0xc5316
movl 0x284(%rsp), %eax
movl %eax, 0x20(%rsp)
jmp 0xc5341
movslq 0x108(%rsp), %rsi
leaq 0x298(%rsp), %rdi
callq 0xc6cc0
movq %rax, 0x18(%rsp)
jmp 0xc5332
movq 0x18(%rsp), %rax
movl 0x20(%rax), %eax
subl $0x1, %eax
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
movl %eax, 0xfc(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xfc(%rsp), %rsi
callq 0xc4a70
movl %eax, 0x104(%rsp)
jmp 0xc5431
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x86b30
jmp 0xc5518
movl $0x0, 0xf8(%rsp)
leaq 0x298(%rsp), %rdi
callq 0x91700
movq %rax, 0x10(%rsp)
jmp 0xc53b2
movq 0x10(%rsp), %rax
decl %eax
movl %eax, 0xf4(%rsp)
leaq 0xf8(%rsp), %rdi
leaq 0xf4(%rsp), %rsi
callq 0xc4a70
movl %eax, 0x108(%rsp)
movl $0x0, 0xf0(%rsp)
movslq 0x108(%rsp), %rsi
leaq 0x298(%rsp), %rdi
callq 0xc6cc0
movq %rax, 0x8(%rsp)
jmp 0xc5403
movq 0x8(%rsp), %rax
movl 0x20(%rax), %eax
subl $0x1, %eax
movl %eax, 0xec(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xec(%rsp), %rsi
callq 0xc4a70
movl %eax, 0x104(%rsp)
movl 0x108(%rsp), %esi
movl 0x104(%rsp), %edx
leaq 0x2d8(%rsp), %rdi
callq 0x86cd0
movb %al, 0x7(%rsp)
jmp 0xc5452
movb 0x7(%rsp), %al
testb $0x1, %al
jne 0xc545c
jmp 0xc54d1
jmp 0xc545e
leaq 0x2d8(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x86190
movb %al, 0x6(%rsp)
jmp 0xc5479
movb 0x6(%rsp), %al
testb $0x1, %al
jne 0xc5483
jmp 0xc54cf
movl 0x1b8(%rsp), %eax
cmpl 0x108(%rsp), %eax
jne 0xc54cd
movl 0x1bc(%rsp), %eax
cmpl 0x104(%rsp), %eax
jl 0xc54cd
leaq 0x288(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x86e80
jmp 0xc54ba
movl 0x10c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10c(%rsp)
jmp 0xc54cf
jmp 0xc545e
jmp 0xc54d1
jmp 0xc5263
leaq 0x2d8(%rsp), %rdi
callq 0x861e0
jmp 0xc54e5
leaq 0x288(%rsp), %rdi
callq 0x86410
jmp 0xc54f4
movb $0x1, 0x527(%rsp)
movl $0x1, 0x300(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x86b30
jmp 0xc5516
jmp 0xc551a
jmp 0xc552b
leaq 0x288(%rsp), %rdi
callq 0x86510
jmp 0xc5529
jmp 0xc553c
leaq 0x288(%rsp), %rdi
callq 0x86510
jmp 0xc553a
jmp 0xc555a
leaq 0x298(%rsp), %rdi
callq 0x91560
jmp 0xc554b
leaq 0x2b0(%rsp), %rdi
callq 0x86f68
jmp 0xc556b
leaq 0x298(%rsp), %rdi
callq 0x91560
jmp 0xc5569
jmp 0xc556d
jmp 0xc557e
leaq 0x2b0(%rsp), %rdi
callq 0x86f68
jmp 0xc557c
jmp 0xc558d
leaq 0x2d8(%rsp), %rdi
callq 0x86150
jmp 0xc559e
leaq 0x2d8(%rsp), %rdi
callq 0x86150
jmp 0xc559c
jmp 0xc55af
movb 0x527(%rsp), %al
andb $0x1, %al
addq $0x528, %rsp            # imm = 0x528
retq
movq 0x308(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopw %cs:(%rax,%rax)