// File: zeeev[P]DASVC/bamtools/src/toolkit/bamtools_filter.cpp
// Function: BamTools::FilterTool::FilterToolPrivate::Run()
bool FilterTool::FilterToolPrivate::Run(void) {
    
    // set to default input if none 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 filter ERROR: could not open input BAM file list... Aborting." << endl;
            return false;
        }

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

    // initialize defined properties & user-specified filters
    // quit if failed
    if ( !SetupFilters() )
        return false;

    // open reader without index
    BamMultiReader reader;
    if ( !reader.Open(m_settings->InputFiles) ) {
        cerr << "bamtools filter ERROR: could not open input files for reading." << endl;
        return false;
    }

    // retrieve reader header & reference data
    const string headerText = reader.GetHeaderText();
    filterToolReferences = reader.GetReferenceData();
    
    // 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, filterToolReferences) ) {
        cerr << "bamtools filter ERROR: could not open " << m_settings->OutputFilename << " for writing." << endl;
        reader.Close();
        return false;
    }

    // if no region specified, filter entire file 
    BamAlignment al;
    if ( !m_settings->HasRegion ) {
        while ( reader.GetNextAlignment(al) ) {
            if ( CheckAlignment(al) ) 
                writer.SaveAlignment(al);
        }
    }
    
    // otherwise attempt to use region as constraint
    else {
        
        // if region string parses OK
        BamRegion region;
        if ( Utilities::ParseRegionString(m_settings->Region, reader, region) ) {

            // attempt to find index files
            reader.LocateIndexes();

            // if index data available for all BAM files, we can use SetRegion
            if ( reader.HasIndexes() ) {

                // attempt to use SetRegion(), if failed report error
                if ( !reader.SetRegion(region.LeftRefID, region.LeftPosition, region.RightRefID, region.RightPosition) ) {
                    cerr << "bamtools filter ERROR: set region failed. Check that REGION describes a valid range" << endl;
                    reader.Close();
                    return false;
                } 
              
                // everything checks out, just iterate through specified region, filtering alignments
                while ( reader.GetNextAlignment(al) )
                    if ( CheckAlignment(al) ) 
                        writer.SaveAlignment(al);
                }
            
            // no index data available, we have to iterate through until we
            // find overlapping alignments
            else {
                while ( reader.GetNextAlignment(al) ) {
                    if ( (al.RefID >= region.LeftRefID)  && ((al.Position + al.Length) >= region.LeftPosition) &&
                         (al.RefID <= region.RightRefID) && ( al.Position <= region.RightPosition) ) 
                    {
                        if ( CheckAlignment(al) ) 
                            writer.SaveAlignment(al);
                    }
                }
            }
        } 
        
        // error parsing REGION string
        else {
            cerr << "bamtools filter 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();
            return false;
        }
    }

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

// Assembly:
subq $0x4c8, %rsp            # imm = 0x4C8
movq %rdi, 0x4b8(%rsp)
movq 0x4b8(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq 0x18(%rax), %rax
testb $0x1, (%rax)
jne 0x9d9c7
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rax
testb $0x1, 0x1(%rax)
jne 0x9d9c7
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rax
addq $0x8, %rax
movq %rax, 0xa0(%rsp)
callq 0x10f280
movq 0xa0(%rsp), %rdi
movq %rax, %rsi
callq 0x91220
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rax
testb $0x1, 0x1(%rax)
je 0x9db84
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rdi
addq $0x20, %rdi
callq 0x86320
movq %rax, %rsi
leaq 0x2b0(%rsp), %rdi
movq %rdi, 0x90(%rsp)
movl $0x8, %edx
callq 0x86e30
movq 0x90(%rsp), %rdi
callq 0x86c10
movb %al, 0x9f(%rsp)
jmp 0x9da25
movb 0x9f(%rsp), %al
testb $0x1, %al
jne 0x9da96
jmp 0x9da32
movq 0xc75a7(%rip), %rdi     # 0x164fe0
leaq 0x91b58(%rip), %rsi     # 0x12f598
callq 0x86700
movq %rax, 0x88(%rsp)
jmp 0x9da4f
movq 0x88(%rsp), %rdi
movq 0xc7512(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0x9da65
movb $0x0, 0x4c7(%rsp)
movl $0x1, 0x2a0(%rsp)
jmp 0x9db4d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x9db70
leaq 0x280(%rsp), %rdi
callq 0x86a30
jmp 0x9daa5
jmp 0x9daa7
leaq 0x2b0(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x86140
movq %rax, 0x80(%rsp)
jmp 0x9dac6
movq 0x80(%rsp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x86b60
movq %rax, 0x78(%rsp)
jmp 0x9dae4
movq 0x78(%rsp), %rax
cmpq $0x0, %rax
je 0x9db33
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rdi
addq $0x8, %rdi
leaq 0x280(%rsp), %rsi
callq 0x91220
jmp 0x9db0e
jmp 0x9daa7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x280(%rsp), %rdi
callq 0x86f68
jmp 0x9db6e
leaq 0x280(%rsp), %rdi
callq 0x86f68
jmp 0x9db42
movl $0x0, 0x2a0(%rsp)
leaq 0x2b0(%rsp), %rdi
callq 0x861c0
movl 0x2a0(%rsp), %eax
testl %eax, %eax
je 0x9db6c
jmp 0x9db67
jmp 0x9e2f5
jmp 0x9db84
jmp 0x9db70
leaq 0x2b0(%rsp), %rdi
callq 0x861c0
jmp 0x9db7f
jmp 0x9e306
movq 0xa8(%rsp), %rdi
callq 0x9e320
testb $0x1, %al
jne 0x9dba2
movb $0x0, 0x4c7(%rsp)
jmp 0x9e2f5
leaq 0x278(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x86db0
movq 0xa8(%rsp), %rax
movq 0x68(%rsp), %rdi
movq 0x18(%rax), %rsi
addq $0x8, %rsi
callq 0x864a0
movb %al, 0x77(%rsp)
jmp 0x9dbd4
movb 0x77(%rsp), %al
testb $0x1, %al
jne 0x9dc3c
jmp 0x9dbde
movq 0xc73fb(%rip), %rdi     # 0x164fe0
leaq 0x919f3(%rip), %rsi     # 0x12f5df
callq 0x86700
movq %rax, 0x60(%rsp)
jmp 0x9dbf8
movq 0x60(%rsp), %rdi
movq 0xc736c(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0x9dc0b
movb $0x0, 0x4c7(%rsp)
movl $0x1, 0x2a0(%rsp)
jmp 0x9e2d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x9e2e4
leaq 0x258(%rsp), %rdi
leaq 0x278(%rsp), %rsi
callq 0x865f0
jmp 0x9dc53
leaq 0x240(%rsp), %rdi
leaq 0x278(%rsp), %rsi
callq 0x862c0
jmp 0x9dc6a
leaq 0xc7fa7(%rip), %rdi     # 0x165c18
leaq 0x240(%rsp), %rsi
callq 0x912a0
jmp 0x9dc80
leaq 0x240(%rsp), %rdi
callq 0x91560
jmp 0x9dc8f
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rax
addq $0x40, %rax
movq %rax, 0x50(%rsp)
callq 0x10f290
movq %rax, 0x58(%rsp)
jmp 0x9dcb0
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rdi
callq 0x91630
movb %al, 0x4f(%rsp)
jmp 0x9dcc5
movb 0x4f(%rsp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, 0x4e(%rsp)
jne 0x9dcd6
jmp 0x9dceb
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rax
movb 0x5(%rax), %al
xorb $-0x1, %al
movb %al, 0x4e(%rsp)
movb 0x4e(%rsp), %al
andb $0x1, %al
movb %al, 0x23f(%rsp)
movl $0x0, 0x238(%rsp)
testb $0x1, 0x23f(%rsp)
je 0x9dd5b
movl $0x1, 0x238(%rsp)
jmp 0x9dd5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x9e2c4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x240(%rsp), %rdi
callq 0x91560
jmp 0x9dd56
jmp 0x9e2c4
leaq 0x230(%rsp), %rdi
callq 0x863f0
jmp 0x9dd6a
leaq 0x230(%rsp), %rdi
leaq 0x238(%rsp), %rsi
callq 0x86280
jmp 0x9dd81
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rsi
addq $0x40, %rsi
leaq 0xc7e80(%rip), %rcx     # 0x165c18
leaq 0x230(%rsp), %rdi
leaq 0x258(%rsp), %rdx
callq 0x86bd0
movb %al, 0x4d(%rsp)
jmp 0x9ddb3
movb 0x4d(%rsp), %al
testb $0x1, %al
jne 0x9de67
jmp 0x9ddc1
movq 0xc7218(%rip), %rdi     # 0x164fe0
leaq 0x9184f(%rip), %rsi     # 0x12f61e
callq 0x86700
movq %rax, 0x40(%rsp)
jmp 0x9dddb
movq 0x40(%rsp), %rdi
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rsi
addq $0x40, %rsi
callq 0x86640
movq %rax, 0x38(%rsp)
jmp 0x9ddfc
movq 0x38(%rsp), %rdi
leaq 0x9183d(%rip), %rsi     # 0x12f645
callq 0x86700
movq %rax, 0x30(%rsp)
jmp 0x9de14
movq 0x30(%rsp), %rdi
movq 0xc7150(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0x9de27
leaq 0x278(%rsp), %rdi
callq 0x861e0
jmp 0x9de36
movb $0x0, 0x4c7(%rsp)
movl $0x1, 0x2a0(%rsp)
jmp 0x9e293
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x9e2b1
leaq 0xd8(%rsp), %rdi
callq 0x86260
jmp 0x9de76
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rax
testb $0x1, 0x3(%rax)
jne 0x9df21
jmp 0x9de8e
leaq 0x278(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86330
movb %al, 0x2f(%rsp)
jmp 0x9dea9
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0x9deb3
jmp 0x9df1c
movq 0xa8(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x9a6c0
movb %al, 0x2e(%rsp)
jmp 0x9dece
movb 0x2e(%rsp), %al
testb $0x1, %al
jne 0x9ded8
jmp 0x9df17
leaq 0x230(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86e80
jmp 0x9deef
jmp 0x9df17
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x86b30
jmp 0x9e291
jmp 0x9de8e
jmp 0x9e24f
movl $0xffffffff, 0xc4(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0xc0(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0xbc(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0xb8(%rsp) # imm = 0xFFFFFFFF
leaq 0xc8(%rsp), %rdi
leaq 0xc4(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
leaq 0xbc(%rsp), %rcx
leaq 0xb8(%rsp), %r8
callq 0x915e0
jmp 0x9df7c
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rdi
addq $0x60, %rdi
leaq 0x278(%rsp), %rsi
leaq 0xc8(%rsp), %rdx
callq 0x115500
movb %al, 0x2d(%rsp)
jmp 0x9dfa7
movb 0x2d(%rsp), %al
testb $0x1, %al
jne 0x9dfb4
jmp 0x9e1b0
movl $0x1, 0xb4(%rsp)
leaq 0x278(%rsp), %rdi
leaq 0xb4(%rsp), %rsi
callq 0x86950
jmp 0x9dfd6
leaq 0x278(%rsp), %rdi
callq 0x864c0
movb %al, 0x2c(%rsp)
jmp 0x9dfe9
movb 0x2c(%rsp), %al
testb $0x1, %al
jne 0x9dff6
jmp 0x9e0f3
leaq 0xcc(%rsp), %rdx
leaq 0xd0(%rsp), %rcx
leaq 0xd4(%rsp), %r8
leaq 0x278(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0x86cf0
movb %al, 0x2b(%rsp)
jmp 0x9e029
movb 0x2b(%rsp), %al
testb $0x1, %al
jne 0x9e087
jmp 0x9e033
movq 0xc6fa6(%rip), %rdi     # 0x164fe0
leaq 0x91612(%rip), %rsi     # 0x12f653
callq 0x86700
movq %rax, 0x20(%rsp)
jmp 0x9e04d
movq 0x20(%rsp), %rdi
movq 0xc6f17(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0x9e060
leaq 0x278(%rsp), %rdi
callq 0x861e0
jmp 0x9e06f
movb $0x0, 0x4c7(%rsp)
movl $0x1, 0x2a0(%rsp)
jmp 0x9e280
jmp 0x9e089
leaq 0x278(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86330
movb %al, 0x1f(%rsp)
jmp 0x9e0a4
movb 0x1f(%rsp), %al
testb $0x1, %al
jne 0x9e0ae
jmp 0x9e0ee
movq 0xa8(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x9a6c0
movb %al, 0x1e(%rsp)
jmp 0x9e0c9
movb 0x1e(%rsp), %al
testb $0x1, %al
jne 0x9e0d3
jmp 0x9e0ec
leaq 0x230(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86e80
jmp 0x9e0ea
jmp 0x9e0ec
jmp 0x9e089
jmp 0x9e1ab
jmp 0x9e0f5
leaq 0x278(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86330
movb %al, 0x1d(%rsp)
jmp 0x9e110
movb 0x1d(%rsp), %al
testb $0x1, %al
jne 0x9e11d
jmp 0x9e1a9
movl 0x180(%rsp), %eax
cmpl 0xc8(%rsp), %eax
jl 0x9e1a4
movl 0x184(%rsp), %eax
addl 0xf8(%rsp), %eax
cmpl 0xcc(%rsp), %eax
jl 0x9e1a4
movl 0x180(%rsp), %eax
cmpl 0xd0(%rsp), %eax
jg 0x9e1a4
movl 0x184(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jg 0x9e1a4
movq 0xa8(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x9a6c0
movb %al, 0x1c(%rsp)
jmp 0x9e17f
movb 0x1c(%rsp), %al
testb $0x1, %al
jne 0x9e189
jmp 0x9e1a2
leaq 0x230(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86e80
jmp 0x9e1a0
jmp 0x9e1a2
jmp 0x9e1a4
jmp 0x9e0f5
jmp 0x9e1ab
jmp 0x9e24d
movq 0xc6e29(%rip), %rdi     # 0x164fe0
leaq 0x914e9(%rip), %rsi     # 0x12f6a7
callq 0x86700
movq %rax, 0x10(%rsp)
jmp 0x9e1ca
movq 0x10(%rsp), %rdi
movq 0xa8(%rsp), %rax
movq 0x18(%rax), %rsi
addq $0x60, %rsi
callq 0x86640
movq %rax, 0x8(%rsp)
jmp 0x9e1eb
movq 0x8(%rsp), %rdi
movq 0xc6d79(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0x9e1fe
movq 0xc6ddb(%rip), %rdi     # 0x164fe0
leaq 0x90148(%rip), %rsi     # 0x12e354
callq 0x86700
movq %rax, (%rsp)
jmp 0x9e217
movq (%rsp), %rdi
movq 0xc6d4e(%rip), %rsi     # 0x164f70
callq 0x86770
jmp 0x9e229
leaq 0x278(%rsp), %rdi
callq 0x861e0
jmp 0x9e238
movb $0x0, 0x4c7(%rsp)
movl $0x1, 0x2a0(%rsp)
jmp 0x9e280
jmp 0x9e24f
leaq 0x278(%rsp), %rdi
callq 0x861e0
jmp 0x9e25e
leaq 0x230(%rsp), %rdi
callq 0x86410
jmp 0x9e26d
movb $0x1, 0x4c7(%rsp)
movl $0x1, 0x2a0(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x86b30
jmp 0x9e28f
jmp 0x9e293
jmp 0x9e2b1
leaq 0x230(%rsp), %rdi
callq 0x86510
jmp 0x9e2a2
leaq 0x258(%rsp), %rdi
callq 0x86f68
jmp 0x9e2c2
leaq 0x230(%rsp), %rdi
callq 0x86510
jmp 0x9e2c0
jmp 0x9e2c4
jmp 0x9e2d5
leaq 0x258(%rsp), %rdi
callq 0x86f68
jmp 0x9e2d3
jmp 0x9e2e4
leaq 0x278(%rsp), %rdi
callq 0x86150
jmp 0x9e2f5
leaq 0x278(%rsp), %rdi
callq 0x86150
jmp 0x9e2f3
jmp 0x9e306
movb 0x4c7(%rsp), %al
andb $0x1, %al
addq $0x4c8, %rsp            # imm = 0x4C8
retq
movq 0x2a8(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopl (%rax,%rax)