// File: 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
movq %rsp, %rbp
subq $0x400, %rsp            # imm = 0x400
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x3430
leaq -0x50(%rbp), %rdi
callq 0x3430
leaq -0x70(%rbp), %rdi
callq 0x3430
leaq -0x90(%rbp), %rdi
callq 0x3430
movb $0x0, -0xa1(%rbp)
movb $0x0, -0xa2(%rbp)
movb $0x0, -0xa3(%rbp)
movb $0x0, -0xa4(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x3430
jmp 0xb81a
movl $0x0, -0xd0(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x2dad(%rip), %rdx      # 0xe5df
leaq 0x8ad7(%rip), %rcx      # 0x14310
leaq -0xd0(%rbp), %r8
callq 0x3500
movl %eax, -0xcc(%rbp)
cmpl $-0x1, -0xcc(%rbp)
jne 0xb859
jmp 0xb9e5
movl -0xcc(%rbp), %eax
movl %eax, -0x35c(%rbp)
testl %eax, %eax
je 0xb8e5
jmp 0xb86b
movl -0x35c(%rbp), %eax
subl $0x3f, %eax
je 0xb9ca
jmp 0xb87c
movl -0x35c(%rbp), %eax
subl $0x63, %eax
je 0xb987
jmp 0xb88d
movl -0x35c(%rbp), %eax
subl $0x64, %eax
je 0xb9b3
jmp 0xb89e
movl -0x35c(%rbp), %eax
subl $0x65, %eax
je 0xb97e
jmp 0xb8af
movl -0x35c(%rbp), %eax
subl $0x68, %eax
je 0xb9bc
jmp 0xb8c0
movl -0x35c(%rbp), %eax
subl $0x69, %eax
je 0xb990
jmp 0xb8d1
movl -0x35c(%rbp), %eax
subl $0x72, %eax
je 0xb999
jmp 0xb9db
movslq -0xd0(%rbp), %rcx
leaq 0x8a1d(%rip), %rax      # 0x14310
shlq $0x5, %rcx
addq %rcx, %rax
cmpq $0x0, 0x10(%rax)
je 0xb906
jmp 0xb9e0
movslq -0xd0(%rbp), %rax
shlq $0x5, %rax
leaq 0x89f8(%rip), %rcx      # 0x14310
movq (%rax,%rcx), %rsi
leaq 0x2cc4(%rip), %rdi      # 0xe5e7
xorl %eax, %eax
callq 0x3060
jmp 0xb92c
movq 0x867d(%rip), %rax      # 0x13fb0
cmpq $0x0, (%rax)
je 0xb96c
movq 0x8670(%rip), %rax      # 0x13fb0
movq (%rax), %rsi
leaq 0x2ca7(%rip), %rdi      # 0xe5f1
xorl %eax, %eax
callq 0x3060
jmp 0xb953
jmp 0xb96c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc322
leaq 0x2c8b(%rip), %rdi      # 0xe5fe
xorl %eax, %eax
callq 0x3060
jmp 0xb97c
jmp 0xb9e0
movb $0x1, -0xa3(%rbp)
jmp 0xb9e0
movb $0x1, -0xa4(%rbp)
jmp 0xb9e0
movb $0x1, -0xa2(%rbp)
jmp 0xb9e0
movq 0x8610(%rip), %rax      # 0x13fb0
movq (%rax), %rsi
leaq -0xc8(%rbp), %rdi
callq 0x3410
jmp 0xb9b1
jmp 0xb9e0
movb $0x1, -0xa1(%rbp)
jmp 0xb9e0
callq 0xb5a0
jmp 0xb9c3
xorl %edi, %edi
callq 0x33b0
callq 0xb5a0
jmp 0xb9d1
movl $0x1, %edi
callq 0x33b0
callq 0x3170
jmp 0xb818
movq 0x85dc(%rip), %rax      # 0x13fc8
movl (%rax), %eax
cmpl -0x8(%rbp), %eax
jge 0xba12
movq -0x10(%rbp), %rax
movq 0x85ca(%rip), %rcx      # 0x13fc8
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rsi
leaq -0x50(%rbp), %rdi
callq 0x3410
jmp 0xba10
jmp 0xba54
movq 0x85d7(%rip), %rdi      # 0x13ff0
leaq 0x2be0(%rip), %rsi      # 0xe600
callq 0x32c0
movq %rax, -0x368(%rbp)
jmp 0xba2e
movq -0x368(%rbp), %rdi
movq 0x856c(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xba43
callq 0xb5a0
jmp 0xba4a
movl $0x1, %edi
callq 0x33b0
testb $0x1, -0xa2(%rbp)
je 0xbc0e
movl $0x280, %edi            # imm = 0x280
callq 0x32e0
movq %rax, -0x370(%rbp)
jmp 0xba74
movq -0x370(%rbp), %rdi
callq 0x39b0
jmp 0xba82
movq -0x370(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x378(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x3130
jmp 0xbab0
movq -0x378(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x4210
jmp 0xbac5
leaq -0x108(%rbp), %rdi
callq 0x31a0
movq -0xe8(%rbp), %rax
movq %rax, -0x380(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x3130
jmp 0xbaf1
movq -0xe8(%rbp), %rsi
leaq -0x168(%rbp), %rdi
callq 0x4c00
jmp 0xbb06
leaq -0x128(%rbp), %rdi
leaq -0x148(%rbp), %rsi
leaq -0x168(%rbp), %rdx
callq 0xc370
jmp 0xbb22
movq -0x380(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x4980
jmp 0xbb37
leaq -0x128(%rbp), %rdi
callq 0x31a0
leaq -0x168(%rbp), %rdi
callq 0x31a0
leaq -0x148(%rbp), %rdi
callq 0x31a0
jmp 0xbc0e
movq -0x370(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
movl $0x280, %esi            # imm = 0x280
callq 0x32f0
jmp 0xc322
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x31a0
jmp 0xc322
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xbbfd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xbbf1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x128(%rbp), %rdi
callq 0x31a0
leaq -0x168(%rbp), %rdi
callq 0x31a0
leaq -0x148(%rbp), %rdi
callq 0x31a0
jmp 0xc322
leaq -0x188(%rbp), %rdi
callq 0x3430
leaq -0x1d0(%rbp), %rdi
callq 0xc440
jmp 0xbc28
leaq -0x1f0(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x3130
jmp 0xbc3a
leaq -0x1d0(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x4c70
jmp 0xbc4f
leaq -0x1f0(%rbp), %rdi
callq 0x31a0
testb $0x1, -0xa1(%rbp)
je 0xbe2f
movq -0x190(%rbp), %rdi
addq $0x30, %rdi
callq 0x5d70
movq %rax, -0x1f8(%rbp)
movq -0x190(%rbp), %rdi
addq $0x30, %rdi
callq 0x5e20
movq %rax, -0x200(%rbp)
leaq -0x1f8(%rbp), %rdi
leaq -0x200(%rbp), %rsi
callq 0xc480
testb $0x1, %al
jne 0xbcb2
jmp 0xbe19
leaq -0x1f8(%rbp), %rdi
callq 0xc4c0
movq %rax, %rsi
movq 0x82f8(%rip), %rdi      # 0x13fc0
callq 0x3290
movq %rax, -0x388(%rbp)
jmp 0xbcd6
movq -0x388(%rbp), %rdi
leaq 0x2331(%rip), %rsi      # 0xe015
callq 0x32c0
movq %rax, -0x390(%rbp)
jmp 0xbcf2
leaq -0x1f8(%rbp), %rdi
callq 0xc4c0
movq %rax, %rsi
leaq -0x240(%rbp), %rdi
callq 0x3130
jmp 0xbd0f
leaq -0x220(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
leaq -0x240(%rbp), %rdx
callq 0x5040
jmp 0xbd2b
movq -0x390(%rbp), %rdi
leaq -0x220(%rbp), %rsi
callq 0x3290
movq %rax, -0x398(%rbp)
jmp 0xbd47
movq -0x398(%rbp), %rdi
movq 0x8253(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xbd5c
leaq -0x220(%rbp), %rdi
callq 0x31a0
leaq -0x240(%rbp), %rdi
callq 0x31a0
leaq -0x1f8(%rbp), %rdi
callq 0xc4e0
jmp 0xbc7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc316
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc30a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0x31a0
jmp 0xc30a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xbe08
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x220(%rbp), %rdi
callq 0x31a0
leaq -0x240(%rbp), %rdi
callq 0x31a0
jmp 0xc30a
movl $0x0, -0x4(%rbp)
movl $0x1, -0x244(%rbp)
jmp 0xc2b3
leaq 0x21e0(%rip), %rsi      # 0xe016
leaq -0xc8(%rbp), %rdi
callq 0x6170
movb %al, -0x399(%rbp)
jmp 0xbe4a
movb -0x399(%rbp), %al
testb $0x1, %al
jne 0xbe59
jmp 0xbeda
leaq -0x270(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0xc500
jmp 0xbe6e
leaq -0x290(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
leaq -0x270(%rbp), %rdx
callq 0x5440
jmp 0xbe8a
leaq -0x188(%rbp), %rdi
leaq -0x290(%rbp), %rsi
callq 0x33c0
leaq -0x290(%rbp), %rdi
callq 0x31a0
leaq -0x270(%rbp), %rdi
callq 0xc7c0
jmp 0xbeda
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x270(%rbp), %rdi
callq 0xc7c0
jmp 0xc30a
testb $0x1, -0xa4(%rbp)
je 0xc17a
leaq -0x2b0(%rbp), %rdi
callq 0x3430
movq 0x80de(%rip), %rdi      # 0x13fd8
leaq -0x2b0(%rbp), %rsi
callq 0x30b0
movq %rax, -0x3a8(%rbp)
jmp 0xbf0f
movq -0x3a8(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x33e0
movb %al, -0x3a9(%rbp)
jmp 0xbf2d
movb -0x3a9(%rbp), %al
testb $0x1, %al
jne 0xbf3c
jmp 0xc158
leaq -0x2d8(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
callq 0xc500
jmp 0xbf51
cmpl $-0x1, -0x2b8(%rbp)
jne 0xc04e
leaq -0x318(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
callq 0x3130
jmp 0xbf73
leaq -0x2f8(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
leaq -0x318(%rbp), %rdx
callq 0x5040
jmp 0xbf8f
movq 0x802a(%rip), %rdi      # 0x13fc0
leaq -0x2f8(%rbp), %rsi
callq 0x3290
movq %rax, -0x3b8(%rbp)
jmp 0xbfab
movq -0x3b8(%rbp), %rdi
movq 0x7fef(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xbfc0
leaq -0x2f8(%rbp), %rdi
callq 0x31a0
leaq -0x318(%rbp), %rdi
callq 0x31a0
jmp 0xc139
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc169
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc14a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc03d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x31a0
leaq -0x318(%rbp), %rdi
callq 0x31a0
jmp 0xc14a
leaq -0x358(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
callq 0x3130
jmp 0xc063
movl -0x2b8(%rbp), %eax
decl %eax
movl %eax, -0x3c0(%rbp)
leaq -0x2d8(%rbp), %rdi
callq 0x6350
movl %eax, -0x3bc(%rbp)
jmp 0xc085
movl -0x3bc(%rbp), %r8d
movl -0x3c0(%rbp), %ecx
leaq -0x338(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
leaq -0x358(%rbp), %rdx
callq 0x5550
jmp 0xc0ae
movq 0x7f0b(%rip), %rdi      # 0x13fc0
leaq -0x338(%rbp), %rsi
callq 0x3290
movq %rax, -0x3c8(%rbp)
jmp 0xc0ca
movq -0x3c8(%rbp), %rdi
movq 0x7ed0(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xc0df
leaq -0x338(%rbp), %rdi
callq 0x31a0
leaq -0x358(%rbp), %rdi
callq 0x31a0
jmp 0xc139
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
jmp 0xc12b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x31a0
leaq -0x358(%rbp), %rdi
callq 0x31a0
jmp 0xc14a
leaq -0x2d8(%rbp), %rdi
callq 0xc7c0
jmp 0xbef3
leaq -0x2d8(%rbp), %rdi
callq 0xc7c0
jmp 0xc169
leaq -0x2b0(%rbp), %rdi
callq 0x31a0
jmp 0xc2a2
leaq -0x2b0(%rbp), %rdi
callq 0x31a0
jmp 0xc30a
leaq 0x1e95(%rip), %rsi      # 0xe016
leaq -0x188(%rbp), %rdi
callq 0x6170
movb %al, -0x3c9(%rbp)
jmp 0xc195
movb -0x3c9(%rbp), %al
testb $0x1, %al
jne 0xc1a4
jmp 0xc2a0
testb $0x1, -0xa3(%rbp)
je 0xc26b
leaq -0x188(%rbp), %rdi
callq 0x31f0
cmpq $0x0, %rax
jbe 0xc236
leaq -0x188(%rbp), %rdi
movq %rdi, -0x3e0(%rbp)
callq 0x3120
movq -0x3e0(%rbp), %rdi
movq %rax, -0x3d8(%rbp)
callq 0x31f0
movq -0x3d8(%rbp), %rdi
movq %rax, %rsi
callq 0xd300
movss %xmm0, -0x3d0(%rbp)
jmp 0xc202
movss -0x3d0(%rbp), %xmm0
movq 0x7daf(%rip), %rdi      # 0x13fc0
callq 0x3210
movq %rax, -0x3e8(%rbp)
jmp 0xc21f
movq -0x3e8(%rbp), %rdi
movq 0x7d7b(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xc234
jmp 0xc269
movq 0x7db3(%rip), %rdi      # 0x13ff0
leaq 0x23d8(%rip), %rsi      # 0xe61c
callq 0x32c0
movq %rax, -0x3f0(%rbp)
jmp 0xc252
movq -0x3f0(%rbp), %rdi
movq 0x7d48(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xc267
jmp 0xc269
jmp 0xc29e
movq 0x7d4e(%rip), %rdi      # 0x13fc0
leaq -0x188(%rbp), %rsi
callq 0x3290
movq %rax, -0x3f8(%rbp)
jmp 0xc287
movq -0x3f8(%rbp), %rdi
movq 0x7d13(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0xc29c
jmp 0xc29e
jmp 0xc2a0
jmp 0xc2a2
movl $0x0, -0x4(%rbp)
movl $0x1, -0x244(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x4fc0
leaq -0x188(%rbp), %rdi
callq 0x31a0
leaq -0xc8(%rbp), %rdi
callq 0x31a0
leaq -0x90(%rbp), %rdi
callq 0x31a0
leaq -0x70(%rbp), %rdi
callq 0x31a0
leaq -0x50(%rbp), %rdi
callq 0x31a0
leaq -0x30(%rbp), %rdi
callq 0x31a0
movl -0x4(%rbp), %eax
addq $0x400, %rsp            # imm = 0x400
popq %rbp
retq
leaq -0x1d0(%rbp), %rdi
callq 0x4fc0
leaq -0x188(%rbp), %rdi
callq 0x31a0
leaq -0xc8(%rbp), %rdi
callq 0x31a0
leaq -0x90(%rbp), %rdi
callq 0x31a0
leaq -0x70(%rbp), %rdi
callq 0x31a0
leaq -0x50(%rbp), %rdi
callq 0x31a0
leaq -0x30(%rbp), %rdi
callq 0x31a0
movq -0xd8(%rbp), %rdi
callq 0x3540
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)