// File: /workspace/github_cpp_makefile_star2_O2/ekg[P]fastahack/FastaHack.cpp
// Function: main
int main (int argc, char** argv) {

    string command;
    string fastaFileName;
    string seqname;
    string longseqname;
    long long start;
    long long length;
    bool dump = false;

    bool buildIndex = false;  // flag to force index building
    bool printEntropy = false;  // entropy printing
    bool readRegionsFromStdin = false;
    //bool printLength = false;
    string region;

    int c;

    while (true) {
        static struct option long_options[] =
        {
            /* These options set a flag. */
            //{"verbose", no_argument,       &verbose_flag, 1},
            //{"brief",   no_argument,       &verbose_flag, 0},
            {"help", no_argument, 0, 'h'},
            {"index",  no_argument, 0, 'i'},
            //{"length",  no_argument, &printLength, true},
            {"entropy", no_argument, 0, 'e'},
            {"region", required_argument, 0, 'r'},
            {"stdin", no_argument, 0, 'c'},
            {0, 0, 0, 0}
        };
        /* getopt_long stores the option index here. */
        int option_index = 0;

        c = getopt_long (argc, argv, "hciedr:",
                         long_options, &option_index);

      /* Detect the end of the options. */
          if (c == -1)
            break;
 
          switch (c)
            {
            case 0:
            /* If this option set a flag, do nothing else now. */
            if (long_options[option_index].flag != 0)
              break;
            printf ("option %s", long_options[option_index].name);
            if (optarg)
              printf (" with arg %s", optarg);
            printf ("\n");
            break;

          case 'e':
            printEntropy = true;
            break;

          case 'c':
            readRegionsFromStdin = true;
            break;
 
          case 'i':
            buildIndex = true;
            break;
 
          case 'r':
            region = optarg;
            break;

            case 'd':
                dump = true;
                break;

          case 'h':
            printSummary();
            exit(0);
            break;
 
          case '?':
            /* getopt_long already printed an error message. */
            printSummary();
            exit(1);
            break;
 
          default:
            abort ();
          }
      }

    /* Print any remaining command line arguments (not options). */
    if (optind < argc) {
        //cerr << "fasta file: " << argv[optind] << endl;
        fastaFileName = argv[optind];
    } else {
        cerr << "please specify a fasta file" << endl;
        printSummary();
        exit(1);
    }

    if (buildIndex) {
        FastaIndex* fai = new FastaIndex();
        //cerr << "generating fasta index file for " << fastaFileName << endl;
        fai->indexReference(fastaFileName);
        fai->writeIndexFile((string) fastaFileName + fai->indexFileExtension());
    }
    
    string sequence;  // holds sequence so we can optionally process it

    FastaReference fr;
    fr.open(fastaFileName);

    if (dump) {
        for (vector<string>::iterator s = fr.index->sequenceNames.begin(); s != fr.index->sequenceNames.end(); ++s) {
            cout << *s << "\t" << fr.getSequence(*s) << endl;
        }
        return 0;
    }

    if (region != "") {
        FastaRegion target(region);
        sequence = fr.getTargetSubSequence(target);
    }

    if (readRegionsFromStdin) {
        string regionstr;
        while (getline(cin, regionstr)) {
            FastaRegion target(regionstr);
            if (target.startPos == -1) {
                cout << fr.getSequence(target.startSeq) << endl;
            } else {
                cout << fr.getSubSequence(target.startSeq, target.startPos - 1, target.length()) << endl;
            }
        }
    } else {
        if (sequence != "") {
            if (printEntropy) {
                if (sequence.size() > 0) {
                    cout << shannon_H((char*) sequence.c_str(), sequence.size()) << endl;
                } else {
                    cerr << "please specify a region or sequence for which to calculate the shannon entropy" << endl;
                }
            } else {  // if no statistical processing is requested, just print the sequence
                cout << sequence << endl;
            }
        }
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x248, %rsp            # imm = 0x248
leaq 0x1d8(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movq %rsi, %rbx
movl %edi, %ebp
xorl %edx, %edx
leaq 0xb8(%rsp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb %dl, (%rax)
movb %dl, (%rcx)
leaq 0x1b8(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
leaq 0x198(%rsp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb %dl, (%rax)
movb %dl, (%rcx)
leaq 0xf8(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movl $0x0, 0x14(%rsp)
movb %dl, (%rax)
leaq 0x22ca(%rip), %r14      # 0x85eb
leaq 0x5f48(%rip), %r15      # 0xc270
leaq 0x60(%rsp), %r12
leaq 0x1ef8(%rip), %r13      # 0x822c
movl $0x0, 0x8(%rsp)
movl $0x0, 0xc(%rsp)
movl $0x0, 0x10(%rsp)
andl $0x0, 0x60(%rsp)
movl %ebp, %edi
movq %rbx, %rsi
movq %r14, %rdx
movq %r15, %rcx
movq %r12, %r8
callq 0x3400
leal -0x63(%rax), %ecx
cmpl $0x6, %ecx
ja 0x637e
movslq (%r13,%rcx,4), %rax
addq %r13, %rax
jmpq *%rax
movb $0x1, %al
movl %eax, 0xc(%rsp)
jmp 0x634c
testl %eax, %eax
je 0x63bc
cmpl $0x72, %eax
jne 0x640f
movq 0x5c1e(%rip), %rax      # 0xbfb0
movq (%rax), %rsi
leaq 0xe8(%rsp), %rdi
callq 0x3470
jmp 0x634c
movb $0x1, %al
movl %eax, 0x10(%rsp)
jmp 0x634c
movb $0x1, %al
movl %eax, 0x8(%rsp)
jmp 0x634c
movb $0x1, %al
movl %eax, 0x14(%rsp)
jmp 0x634c
movslq 0x60(%rsp), %rax
shlq $0x5, %rax
cmpq $0x0, 0x10(%rax,%r15)
jne 0x634c
addq %r15, %rax
movq (%rax), %rsi
leaq 0x2215(%rip), %rdi      # 0x85f3
xorl %eax, %eax
callq 0x3040
movq 0x5bc4(%rip), %rax      # 0xbfb0
movq (%rax), %rsi
testq %rsi, %rsi
je 0x6402
leaq 0x2202(%rip), %rdi      # 0x85fd
xorl %eax, %eax
callq 0x3040
pushq $0xa
popq %rdi
callq 0x3350
jmp 0x634c
cmpl $-0x1, %eax
jne 0x6860
movq 0x5ba9(%rip), %rax      # 0xbfc8
movslq (%rax), %rax
cmpl %ebp, %eax
jge 0x6883
movq (%rbx,%rax,8), %rsi
leaq 0xa8(%rsp), %rdi
callq 0x3470
testb $0x1, 0x14(%rsp)
je 0x64f4
movl $0x280, %edi            # imm = 0x280
callq 0x3270
movq %rax, %r14
movq %rax, %rdi
callq 0x3750
leaq 0x148(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x3330
leaq 0x148(%rsp), %rsi
movq %r14, %rdi
callq 0x3c2c
leaq 0x148(%rsp), %rdi
callq 0x3120
leaq 0x60(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x3330
leaq 0x18(%rsp), %rdi
movq %r14, %rsi
callq 0x420a
leaq 0x128(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x6a1b
leaq 0x128(%rsp), %rsi
movq %r14, %rdi
callq 0x40a4
leaq 0x128(%rsp), %rdi
callq 0x3120
leaq 0x18(%rsp), %rdi
callq 0x3120
leaq 0x60(%rsp), %rdi
callq 0x3120
leaq 0x50(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
leaq 0x78(%rsp), %rdx
movb %cl, -0x18(%rdx)
movq %rdx, -0x10(%rdx)
andq $0x0, -0x8(%rdx)
movb %cl, (%rdx)
andq $0x0, 0x10(%rdx)
movb %cl, (%rax)
andq $0x0, 0x28(%rdx)
leaq 0x108(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x3330
leaq 0x60(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x422c
leaq 0x108(%rsp), %rdi
callq 0x3120
testb $0x1, 0x10(%rsp)
je 0x65f4
leaq 0x60(%rsp), %rbx
movq 0x40(%rbx), %rax
movq 0x30(%rax), %r14
leaq 0x1a8f(%rip), %r12      # 0x8005
leaq 0x228(%rsp), %r13
leaq 0x18(%rsp), %rbp
cmpq 0x38(%rax), %r14
je 0x67f7
movq 0x5a2c(%rip), %rdi      # 0xbfc0
movq %r14, %rsi
callq 0x3220
movq %rax, %rdi
movq %r12, %rsi
callq 0x3250
movq %rax, %r15
movq %r13, %rdi
movq %r14, %rsi
callq 0x3330
movq %rbp, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x443e
movq %r15, %rdi
movq %rbp, %rsi
callq 0x3220
movq %rax, %rdi
callq 0x3130
movq %rbp, %rdi
callq 0x3120
movq %r13, %rdi
callq 0x3120
addq $0x20, %r14
movq 0xa0(%rsp), %rax
jmp 0x6583
leaq 0x1a0b(%rip), %rsi      # 0x8006
leaq 0xe8(%rsp), %rdi
callq 0x4a5f
testb %al, %al
je 0x665c
leaq 0x18(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x6a82
leaq 0xc8(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x462c
leaq 0x40(%rsp), %rdi
leaq 0xc8(%rsp), %rbx
movq %rbx, %rsi
callq 0x3300
movq %rbx, %rdi
callq 0x3120
leaq 0x18(%rsp), %rdi
callq 0x3120
testb $0x1, 0xc(%rsp)
je 0x677c
leaq 0xd8(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0xc8(%rsp), %r14
leaq 0x18(%rsp), %r15
leaq 0x208(%rsp), %r12
leaq 0x168(%rsp), %r13
movq 0x5921(%rip), %rbp      # 0xbfc0
leaq 0x1e8(%rsp), %rbx
movq 0x592a(%rip), %rdi      # 0xbfd8
movq %r14, %rsi
callq 0x3080
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x67ba
movq %r15, %rdi
movq %r14, %rsi
callq 0x6a82
cmpl $-0x1, 0x38(%rsp)
je 0x6731
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3330
movl 0x38(%rsp), %ecx
movl 0x3c(%rsp), %eax
movl %eax, %r8d
subl %ecx, %r8d
decl %ecx
incl %r8d
testl %eax, %eax
pushq $0x1
popq %rax
cmovlel %eax, %r8d
movq %r13, %rdi
leaq 0x60(%rsp), %rsi
movq %rbx, %rdx
callq 0x46d6
movq %rbp, %rdi
movq %r13, %rsi
callq 0x3220
movq %rax, %rdi
callq 0x3130
movq %r13, %rdi
callq 0x3120
movq %rbx, %rdi
jmp 0x676a
movq %r12, %rdi
movq %r15, %rsi
callq 0x3330
movq %r13, %rdi
leaq 0x60(%rsp), %rsi
movq %r12, %rdx
callq 0x443e
movq %rbp, %rdi
movq %r13, %rsi
callq 0x3220
movq %rax, %rdi
callq 0x3130
movq %r13, %rdi
callq 0x3120
movq %r12, %rdi
callq 0x3120
movq %r15, %rdi
callq 0x3120
jmp 0x66a7
leaq 0x1883(%rip), %rsi      # 0x8006
leaq 0x40(%rsp), %rdi
callq 0x4a5f
testb %al, %al
je 0x67f7
testb $0x1, 0x8(%rsp)
je 0x67c9
movq 0x48(%rsp), %rsi
testq %rsi, %rsi
je 0x67dc
movq 0x40(%rsp), %rdi
callq 0x6ff4
movq 0x580d(%rip), %rdi      # 0xbfc0
callq 0x31c0
jmp 0x67ef
leaq 0xc8(%rsp), %rdi
callq 0x3120
jmp 0x67f7
movq 0x57f0(%rip), %rdi      # 0xbfc0
leaq 0x40(%rsp), %rsi
callq 0x3220
jmp 0x67ef
movq 0x580d(%rip), %rdi      # 0xbff0
leaq 0x1e3c(%rip), %rsi      # 0x8626
callq 0x3250
movq %rax, %rdi
callq 0x3130
leaq 0x60(%rsp), %rdi
callq 0x43f8
leaq 0x40(%rsp), %rdi
callq 0x3120
leaq 0xe8(%rsp), %rdi
callq 0x3120
leaq 0x188(%rsp), %rdi
callq 0x3120
leaq 0x1a8(%rsp), %rdi
callq 0x3120
leaq 0xa8(%rsp), %rdi
callq 0x3120
leaq 0x1c8(%rsp), %rdi
callq 0x3120
xorl %eax, %eax
addq $0x248, %rsp            # imm = 0x248
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x3f, %eax
jne 0x6872
callq 0x611c
pushq $0x1
popq %rdi
callq 0x32f0
callq 0x3160
callq 0x611c
xorl %edi, %edi
callq 0x32f0
movq 0x5766(%rip), %rdi      # 0xbff0
leaq 0x1d79(%rip), %rsi      # 0x860a
callq 0x3250
movq %rax, %rdi
callq 0x3130
callq 0x611c
jmp 0x686a
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
jmp 0x69ad
jmp 0x69b4
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
callq 0x3120
jmp 0x68cc
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x3120
jmp 0x68db
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
jmp 0x69c6
jmp 0x69cf
movq %rax, %rbx
leaq 0x148(%rsp), %rdi
jmp 0x69c6
movq %rax, %rbx
movl $0x280, %esi            # imm = 0x280
movq %r14, %rdi
callq 0x3280
jmp 0x69d2
movq %rax, %rbx
leaq 0x108(%rsp), %rdi
jmp 0x69ad
jmp 0x69cf
jmp 0x69cf
jmp 0x69b4
movq %rax, %rbx
jmp 0x694f
jmp 0x693a
movq %rax, %rbx
jmp 0x6970
movq %rax, %rbx
jmp 0x697d
movq %rax, %rbx
leaq 0x168(%rsp), %rdi
callq 0x3120
leaq 0x208(%rsp), %rdi
jmp 0x6978
jmp 0x695b
movq %rax, %rbx
jmp 0x6987
movq %rax, %rbx
leaq 0x168(%rsp), %rdi
callq 0x3120
leaq 0x1e8(%rsp), %rdi
callq 0x3120
leaq 0x18(%rsp), %rdi
callq 0x3120
leaq 0xc8(%rsp), %rdi
jmp 0x69ad
jmp 0x69b4
movq %rax, %rbx
jmp 0x69a5
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x3120
leaq 0x228(%rsp), %rdi
callq 0x3120
jmp 0x69b7
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x43f8
leaq 0x40(%rsp), %rdi
callq 0x3120
jmp 0x69d2
jmp 0x69cf
movq %rax, %rbx
leaq 0xe8(%rsp), %rdi
callq 0x3120
leaq 0x188(%rsp), %rdi
callq 0x3120
leaq 0x1a8(%rsp), %rdi
callq 0x3120
leaq 0xa8(%rsp), %rdi
callq 0x3120
leaq 0x1c8(%rsp), %rdi
callq 0x3120
movq %rbx, %rdi
callq 0x3430