// File: /workspace/github_cpp_makefile_star2_O2/jorbs[P]stellar-keypair-tool/keypair.cpp
// Function: main
int main(int argc, char* argv[]) {
  if (argc == 1) {
    usage(argv[0]);
    return 1;
  }

  std::string term;
  int threadsCount = -1, c;
  bool (*matchFunction)(const std::string &input, const std::string &suffix);

  while ((c = getopt(argc, argv, "p:m:s:j:")) != -1) {
    switch (c) {
      case 'p':
        if (optarg[0] != 'g' && optarg[0] != 'G') {
          std::cout << "Prepending 'G' to the search term.\n";
          term = "G";
        }

        term += optarg;
        matchFunction = &hasPrefix;
        break;
      case 's':
        term = optarg;
        matchFunction = &hasSuffix;
        break;
      case 'm':
        term = optarg;
        matchFunction = &hasSubstr;
        break;
      case 'j':
        threadsCount = atoi(optarg);
        break;
      case '?':
      default:
        usage(argv[0]);
        return 0;
    }
  }

  if (threadsCount < 1) {
    threadsCount = getProcessingUnits();
  }

  std::transform(term.begin(), term.end(), term.begin(), ::toupper);

  char invalidChar = checkInvalidChar(term);

  if (invalidChar != -1) {
    std::cerr << "\"" << invalidChar << "\" is not allowed. The search term must be scoped to:\n\t"
              << base32Dictionary << std::endl;
    return 0;
  }

  if (sodium_init() == -1) {
    std::cerr << "Unable to init libsodium.\n";
    return 1;
  }

  std::cout << "Searching...\n";

  std::vector<std::thread> threads(threadsCount);
  auto start = std::chrono::system_clock::now();

  for (int i = 0; i < threadsCount; i++)
    threads[i] = std::thread(process, term, matchFunction);

  std::for_each(threads.begin(), threads.end(), [](std::thread &t) { t.join(); });

  auto end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end - start;

  std::cout << count << " tries in "
            << elapsed_seconds.count() << "s using "
            << threadsCount << " threads.\n";

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %r14
cmpl $0x1, %edi
jne 0x27a8
movq (%r14), %rdi
callq 0x258f
pushq $0x1
popq %rbx
jmp 0x2a64
movl %edi, %ebp
leaq 0x48(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
pushq $-0x1
popq %rax
movl %eax, 0x4(%rsp)
leaq 0x190a(%rip), %r15      # 0x40d3
leaq 0x1840(%rip), %rbx      # 0x4010
movq 0x47e9(%rip), %r13      # 0x6fc0
leaq 0x38(%rsp), %r12
movl %ebp, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x2040
leal -0x6a(%rax), %ecx
cmpl $0x9, %ecx
ja 0x2892
movslq (%rbx,%rcx,4), %rax
addq %rbx, %rax
jmpq *%rax
movq (%r13), %rsi
movq %r12, %rdi
callq 0x22d0
leaq 0x475(%rip), %rax       # 0x2c86
movq %rax, 0x8(%rsp)
jmp 0x27dc
movq (%r13), %rsi
movq %r12, %rdi
callq 0x22d0
leaq 0x417(%rip), %rax       # 0x2c42
movq %rax, 0x8(%rsp)
jmp 0x27dc
movq (%r13), %rsi
movzbl (%rsi), %eax
orl $0x20, %eax
cmpl $0x67, %eax
je 0x2867
movq 0x4788(%rip), %rdi      # 0x6fd0
leaq 0x188d(%rip), %rsi      # 0x40dc
callq 0x2180
movq %r12, %rdi
leaq 0x18a2(%rip), %rsi      # 0x4100
callq 0x22d0
movq (%r13), %rsi
movq %r12, %rdi
callq 0x22c0
leaq 0x38d(%rip), %rax       # 0x2c03
movq %rax, 0x8(%rsp)
jmp 0x27dc
movq (%r13), %rdi
callq 0x2220
movl %eax, 0x4(%rsp)
jmp 0x27dc
cmpl $-0x1, %eax
jne 0x28cc
cmpl $0x0, 0x4(%rsp)
jg 0x28a7
callq 0x24a8
movl %eax, 0x4(%rsp)
movq 0x38(%rsp), %rbx
movq 0x40(%rsp), %r14
xorl %r15d, %r15d
cmpq %r15, %r14
je 0x28d9
movsbl (%rbx,%r15), %edi
callq 0x22b0
movb %al, (%rbx,%r15)
incq %r15
jmp 0x28b4
movq (%r14), %rdi
callq 0x258f
jmp 0x2a58
leaq 0x38(%rsp), %rdi
callq 0x245c
cmpb $-0x1, %al
je 0x2932
movl %eax, %ebx
movq 0x4700(%rip), %rdi      # 0x6ff0
leaq 0x180b(%rip), %rsi      # 0x4102
callq 0x2180
movsbl %bl, %esi
movq %rax, %rdi
callq 0x21c0
leaq 0x17f6(%rip), %rsi      # 0x4104
movq %rax, %rdi
callq 0x2180
leaq 0x4883(%rip), %rsi      # 0x71a0
movq %rax, %rdi
callq 0x2160
movq %rax, %rdi
callq 0x20b0
jmp 0x2a58
callq 0x2290
cmpl $-0x1, %eax
je 0x2a75
movq 0x4689(%rip), %rdi      # 0x6fd0
leaq 0x1808(%rip), %rsi      # 0x4156
callq 0x2180
movl 0x4(%rsp), %r14d
leaq 0x20(%rsp), %rdi
leaq 0x18(%rsp), %rdx
movq %r14, %rsi
callq 0x2c98
callq 0x2030
movq %rax, 0x10(%rsp)
shlq $0x3, %r14
xorl %ebx, %ebx
leaq -0x3c0(%rip), %r15      # 0x25c1
leaq 0x18(%rsp), %r12
leaq 0x38(%rsp), %r13
leaq 0x8(%rsp), %rbp
cmpq %rbx, %r14
je 0x29c4
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %rbp, %rcx
callq 0x2cea
movq 0x20(%rsp), %rdi
addq %rbx, %rdi
movq %r12, %rsi
callq 0x2d7e
movq %r12, %rdi
callq 0x2d98
addq $0x8, %rbx
jmp 0x2990
movq 0x20(%rsp), %r14
movq 0x28(%rsp), %rbx
cmpq %rbx, %r14
je 0x29e1
movq %r14, %rdi
callq 0x2260
addq $0x8, %r14
jmp 0x29ce
callq 0x2030
movq %rax, %r14
movl 0x47d5(%rip), %esi      # 0x71c4
movq 0x45da(%rip), %rdi      # 0x6fd0
callq 0x2270
leaq 0x1762(%rip), %rsi      # 0x4164
movq %rax, %rdi
callq 0x2180
subq 0x10(%rsp), %r14
cvtsi2sd %r14, %xmm0
divsd 0x15ec(%rip), %xmm0     # 0x4008
movq %rax, %rdi
callq 0x2240
leaq 0x1744(%rip), %rsi      # 0x416f
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl 0x4(%rsp), %esi
callq 0x2270
leaq 0x1732(%rip), %rsi      # 0x4178
movq %rax, %rdi
callq 0x2180
leaq 0x20(%rsp), %rdi
callq 0x2da6
xorl %ebx, %ebx
leaq 0x38(%rsp), %rdi
callq 0x22f8
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x4574(%rip), %rdi      # 0x6ff0
leaq 0x16b8(%rip), %rsi      # 0x413b
callq 0x2180
pushq $0x1
popq %rbx
jmp 0x2a5a
jmp 0x2aa6
jmp 0x2a97
jmp 0x2aa6
jmp 0x2aa6
jmp 0x2a97
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x2da6
jmp 0x2aa9
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x22f8
movq %rbx, %rdi
callq 0x2280
nop