// File: onfe[P]Completionist/src/suggest.cpp
// Function: suggest(PhraseList&, SegmentTree&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&, unsigned int)
pvc_t suggest (
  PhraseList& pl,
  SegmentTree& st,
  std::string& prefix,
  uint32_t numResults = 16
) {
  // Get the pointers [first, last] for the candidate phrases.
  pvcip_t candidates = pl.query(prefix);

  // transform the pointers to indexes.
  uint32_t first = candidates.first - pl.pl.begin();
  uint32_t last = candidates.second - pl.pl.begin();

  // if there are no results, return an empty phrase vector.
  if (first == last) { return pvc_t(); }

  // the indexes are from first match to next non-match
  // decrement the last index to instead use first - last match.
  --last;
  pvc_t results;

  // The queue automatically orders elements so that .top() returns the largest element.
  // in this case, the largest element is the phrase range with the greatest weight.
  std::priority_queue<PhraseRange> queue;
  uip_t best = st.getMax(first, last);
  queue.emplace(first, last, best.first, best.second);

  while (results.size() < numResults && !queue.empty()) {
    PhraseRange curr = queue.top();
    queue.pop();

    // The best result is added to the result
    results.push_back(pl.pl[curr.index]);

    uint32_t lo = curr.first;
    uint32_t hi = curr.index - 1;

    // Check for underflows in indexing.
    if (curr.index -1 < curr.index && lo <= hi) {
      // index is ok, so add to queue.
      best = st.getMax(lo, hi);
      queue.emplace(lo, hi, best.first, best.second);
    }

    lo = curr.index + 1;
    hi = curr.last;

    // Check for overflows in indexing.
    if (curr.index + 1 > curr.index && lo <= hi) {
      // index is ok, so add to queue.
      best = st.getMax(lo, hi);
      queue.emplace(lo, hi, best.first, best.second);
    }
  }

  return results;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rdi, -0x108(%rbp)
movq %rdi, %rax
movq %rax, -0x100(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0x20(%rbp), %rsi
leaq -0x58(%rbp), %rdi
movq %rdi, -0xf0(%rbp)
callq 0x20c0
movq -0xf8(%rbp), %rdi
movq -0xf0(%rbp), %rsi
callq 0x77f0
movq %rdx, -0xe8(%rbp)
movq %rax, -0xe0(%rbp)
jmp 0x5242
movq -0xe8(%rbp), %rax
movq -0xe0(%rbp), %rcx
movq %rcx, -0x38(%rbp)
movq %rax, -0x30(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x2130
leaq -0x38(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5660
movq -0x118(%rbp), %rdi
movq %rax, -0x70(%rbp)
leaq -0x70(%rbp), %rsi
callq 0x5610
movl %eax, -0x68(%rbp)
leaq -0x38(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x110(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5660
movq -0x110(%rbp), %rdi
movq %rax, -0x80(%rbp)
leaq -0x80(%rbp), %rsi
callq 0x5610
movl %eax, -0x74(%rbp)
movl -0x68(%rbp), %eax
cmpl -0x74(%rbp), %eax
jne 0x5301
movq -0x108(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x2100
movq -0x108(%rbp), %rdi
callq 0x5690
jmp 0x55ed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x2130
jmp 0x55fd
movq -0x108(%rbp), %rdi
movl -0x74(%rbp), %eax
decl %eax
movl %eax, -0x74(%rbp)
movb $0x0, -0x81(%rbp)
callq 0x5690
leaq -0xa8(%rbp), %rdi
callq 0x56b0
jmp 0x532a
movq -0x18(%rbp), %rdi
movl -0x68(%rbp), %esi
movl -0x74(%rbp), %edx
callq 0x9c60
movq %rax, -0x120(%rbp)
jmp 0x5342
movq -0x120(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0xac(%rbp), %r8
leaq -0xa8(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0x74(%rbp), %rdx
leaq -0xb0(%rbp), %rcx
callq 0x56e0
jmp 0x5374
jmp 0x5376
movq -0x108(%rbp), %rdi
callq 0x2c80
movq %rax, %rcx
movl -0x24(%rbp), %eax
movl %eax, %edx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0x121(%rbp)
jae 0x53b9
leaq -0xa8(%rbp), %rdi
callq 0x5750
movb %al, -0x122(%rbp)
jmp 0x53ab
movb -0x122(%rbp), %al
xorb $-0x1, %al
movb %al, -0x121(%rbp)
movb -0x121(%rbp), %al
testb $0x1, %al
jne 0x53c8
jmp 0x55b5
leaq -0xa8(%rbp), %rdi
callq 0x5770
movq %rax, -0x130(%rbp)
jmp 0x53dd
movq -0x130(%rbp), %rax
movups (%rax), %xmm0
movaps %xmm0, -0xc0(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x5790
jmp 0x53fc
movq -0x10(%rbp), %rdi
movl -0xb4(%rbp), %eax
movl %eax, %esi
callq 0x2d30
movq -0x108(%rbp), %rdi
movq %rax, %rsi
callq 0x57e0
jmp 0x541e
movl -0xc0(%rbp), %eax
movl %eax, -0xc4(%rbp)
movl -0xb4(%rbp), %eax
subl $0x1, %eax
movl %eax, -0xc8(%rbp)
movl -0xb4(%rbp), %eax
subl $0x1, %eax
cmpl -0xb4(%rbp), %eax
jae 0x5500
movl -0xc4(%rbp), %eax
cmpl -0xc8(%rbp), %eax
ja 0x5500
movq -0x18(%rbp), %rdi
movl -0xc4(%rbp), %esi
movl -0xc8(%rbp), %edx
callq 0x9c60
movq %rax, -0x138(%rbp)
jmp 0x547e
movq -0x138(%rbp), %rax
movq %rax, -0xd0(%rbp)
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x140(%rbp)
leaq -0xd0(%rbp), %rsi
callq 0x5850
movq -0x140(%rbp), %rcx
leaq -0xac(%rbp), %r8
leaq -0xa8(%rbp), %rdi
leaq -0xc4(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
callq 0x56e0
jmp 0x54d0
jmp 0x5500
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x55df
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x5880
jmp 0x55df
movl -0xb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
movl -0xbc(%rbp), %eax
movl %eax, -0xc8(%rbp)
movl -0xb4(%rbp), %eax
addl $0x1, %eax
cmpl -0xb4(%rbp), %eax
jbe 0x55b0
movl -0xc4(%rbp), %eax
cmpl -0xc8(%rbp), %eax
ja 0x55b0
movq -0x18(%rbp), %rdi
movl -0xc4(%rbp), %esi
movl -0xc8(%rbp), %edx
callq 0x9c60
movq %rax, -0x148(%rbp)
jmp 0x555c
movq -0x148(%rbp), %rax
movq %rax, -0xd8(%rbp)
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x150(%rbp)
leaq -0xd8(%rbp), %rsi
callq 0x5850
movq -0x150(%rbp), %rcx
leaq -0xac(%rbp), %r8
leaq -0xa8(%rbp), %rdi
leaq -0xc4(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
callq 0x56e0
jmp 0x55ae
jmp 0x55b0
jmp 0x5376
movb $0x1, -0x81(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x5880
testb $0x1, -0x81(%rbp)
jne 0x55dd
movq -0x108(%rbp), %rdi
callq 0x2d50
jmp 0x55ed
movq -0x108(%rbp), %rdi
callq 0x2d50
jmp 0x55fd
movq -0x100(%rbp), %rax
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x2260
nopw %cs:(%rax,%rax)