// File: chhylp123[P]hifiasm/hic.cpp
// Function: get_longest_hit(char*, unsigned long, unsigned long, unsigned long, unsigned long, kvec_vote*, ha_ug_index const*, unsigned long*, unsigned long, unsigned long*)
uint64_t get_longest_hit(char *r, uint64_t len, uint64_t k_mer, uint64_t self_p, uint64_t self_rev, kvec_vote* buf, const ha_ug_index* idx, 
uint64_t *pos_list, uint64_t cnt, uint64_t* c_sfx)
{
    uint64_t max_p, map_p_occ, i, j, m, rev, ref_p, u_len, uID, k_len;
    s_hit *p = NULL;
    ///each k-mer at different unitigs
    ///rev:uID:pos
    if(c_sfx) (*c_sfx) = (uint64_t)-1;
    for (j = 0; j < cnt; j++)
    {
        ///get
        kv_pushp(s_hit, buf->a, &p);
        rev = (pos_list[j]>>63) != self_rev;
        ref_p = pos_list[j] & idx->pos_mode;
        uID = (pos_list[j] << 1) >> (64 - idx->uID_bits);
        u_len = idx->ug->u.a[uID].len;
        if(rev) ref_p = u_len - 1 - (ref_p + 1 - k_mer);
        p->off_cnt = self_p | ((uint64_t)k_mer << 32); ///high bits should be the legnth

        p->ref = ref_p >= self_p? (ref_p-self_p) 
                        : (self_p-ref_p) + ((uint64_t)1 << (idx->pos_bits - 1));
        p->ref = (rev << 63)|(pos_list[j] & idx->uID_mode)|(p->ref&idx->pos_mode);


        ///extend
        k_len = check_exact_match(r, self_p + 1, len, idx->ug->u.a[uID].s, ref_p + 1, u_len, len, rev, 0);
        if(c_sfx && cnt == idx->hap_cnt && k_len < (*c_sfx)) (*c_sfx) = k_len;
        
        p->off_cnt += ((uint64_t)k_len << 32) + k_len;

        if(self_p >= k_mer && ref_p >= k_mer)
        {
            k_len = check_exact_match(r, self_p - k_mer, len, idx->ug->u.a[uID].s, 
                                                    ref_p - k_mer, u_len, len, rev, 1);
            p->off_cnt += ((uint64_t)k_len << 32);
        }
        // if(cnt > 0) fprintf(stderr, "inner j: %lu, rev: %lu, uID: %lu, ref_p: %lu, self_p: %u, len: %lu\n", j, rev, uID, ref_p, (uint32_t)p->off_cnt, p->off_cnt>>32);
    }

    p = buf->a.a + buf->a.n - cnt;
    if(cnt > 1) radix_sort_hc_s_hit_off_cnt(p, p + cnt);
    max_p = map_p_occ = 0; 
    for (j = 1, i = 0; j <= cnt; ++j)
    {
        if(j == cnt || p[j].off_cnt != p[i].off_cnt)
        {
            if((max_p>>32) < (p[i].off_cnt>>32))
            {
                max_p = p[i].off_cnt;
                map_p_occ = j - i;
            }
            else if(((max_p>>32) == (p[i].off_cnt>>32)) && ((j - i) > map_p_occ))
            {
                max_p = p[i].off_cnt;
                map_p_occ = j - i;
            }
            i = j;///must
        }
    }

    buf->a.n -= cnt;
    for (j = m = 0; j < cnt; j++)
    {
        if(p[j].off_cnt == max_p)
        {
            p[m] = p[j];
            m++;
        }
    }
    cnt = m;
    buf->a.n += cnt;
    
    // if(cnt > 0) fprintf(stderr, "max_p_offset: %u, max_p_len: %lu, map_p_occ: %lu\n", (uint32_t)max_p, max_p>>32, map_p_occ);
    return max_p;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq 0x28(%rbp), %rax
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq $0x0, -0x88(%rbp)
cmpq $0x0, 0x28(%rbp)
je 0x1c1e50
movq 0x28(%rbp), %rax
movq $-0x1, (%rax)
movq $0x0, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpq 0x20(%rbp), %rax
jae 0x1c217f
jmp 0x1c1e68
movq -0x30(%rbp), %rax
movq (%rax), %rax
movq -0x30(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jne 0x1c1ed9
movq -0x30(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x1c1e98
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
shlq %rax
movq %rax, -0x90(%rbp)
jmp 0x1c1ea6
movl $0x2, %eax
movq %rax, -0x90(%rbp)
jmp 0x1c1ea6
movq -0x90(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rsi
shlq $0x4, %rsi
callq 0x2360
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x30(%rbp), %rdx
movq (%rdx), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, (%rdx)
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x88(%rbp)
movq 0x18(%rbp), %rax
movq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
shrq $0x3f, %rax
cmpq -0x28(%rbp), %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movq %rax, -0x60(%rbp)
movq 0x18(%rbp), %rax
movq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x10(%rbp), %rcx
andq 0x30(%rcx), %rax
movq %rax, -0x68(%rbp)
movq 0x18(%rbp), %rax
movq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
shlq %rax
movq 0x10(%rbp), %rdx
movl $0x40, %ecx
subq 0x18(%rdx), %rcx
shrq %cl, %rax
movq %rax, -0x78(%rbp)
movq 0x10(%rbp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
imulq $0x28, -0x78(%rbp), %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, %eax
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x60(%rbp)
je 0x1c1f9d
movq -0x70(%rbp), %rax
subq $0x1, %rax
movq -0x68(%rbp), %rcx
addq $0x1, %rcx
subq -0x18(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x68(%rbp)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
shlq $0x20, %rax
orq %rax, %rcx
movq -0x88(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x68(%rbp), %rax
cmpq -0x20(%rbp), %rax
jb 0x1c1fd2
movq -0x68(%rbp), %rax
subq -0x20(%rbp), %rax
movq %rax, -0x98(%rbp)
jmp 0x1c1ffb
movq -0x20(%rbp), %rax
subq -0x68(%rbp), %rax
movq 0x10(%rbp), %rcx
movq 0x28(%rcx), %rcx
subq $0x1, %rcx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rcx
movq -0x88(%rbp), %rax
movq %rcx, (%rax)
movq -0x60(%rbp), %rcx
shlq $0x3f, %rcx
movq 0x18(%rbp), %rax
movq -0x50(%rbp), %rdx
movq (%rax,%rdx,8), %rax
movq 0x10(%rbp), %rdx
andq 0x20(%rdx), %rax
orq %rax, %rcx
movq -0x88(%rbp), %rax
movq (%rax), %rax
movq 0x10(%rbp), %rdx
andq 0x30(%rdx), %rax
orq %rax, %rcx
movq -0x88(%rbp), %rax
movq %rcx, (%rax)
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
addq $0x1, %rsi
movq -0x10(%rbp), %rdx
movq 0x10(%rbp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
imulq $0x28, -0x78(%rbp), %rcx
addq %rcx, %rax
movq 0x20(%rax), %rcx
movq -0x68(%rbp), %r8
addq $0x1, %r8
movq -0x70(%rbp), %r9
movq -0x10(%rbp), %r10
movq -0x60(%rbp), %rax
xorl %r11d, %r11d
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movq $0x0, 0x10(%rsp)
callq 0x213270
movq %rax, -0x80(%rbp)
cmpq $0x0, 0x28(%rbp)
je 0x1c20d0
movq 0x20(%rbp), %rax
movq 0x10(%rbp), %rcx
cmpq 0x48(%rcx), %rax
jne 0x1c20d0
movq -0x80(%rbp), %rax
movq 0x28(%rbp), %rcx
cmpq (%rcx), %rax
jae 0x1c20d0
movq -0x80(%rbp), %rcx
movq 0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x80(%rbp), %rcx
shlq $0x20, %rcx
addq -0x80(%rbp), %rcx
movq -0x88(%rbp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
cmpq -0x18(%rbp), %rax
jb 0x1c216c
movq -0x68(%rbp), %rax
cmpq -0x18(%rbp), %rax
jb 0x1c216c
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
subq -0x18(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq 0x10(%rbp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
imulq $0x28, -0x78(%rbp), %rcx
addq %rcx, %rax
movq 0x20(%rax), %rcx
movq -0x68(%rbp), %r8
subq -0x18(%rbp), %r8
movq -0x70(%rbp), %r9
movq -0x10(%rbp), %r10
movq -0x60(%rbp), %rax
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movq $0x1, 0x10(%rsp)
callq 0x213270
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rcx
shlq $0x20, %rcx
movq -0x88(%rbp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
jmp 0x1c216e
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
jmp 0x1c1e58
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x30(%rbp), %rcx
movq (%rcx), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
xorl %ecx, %ecx
subq 0x20(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x88(%rbp)
cmpq $0x1, 0x20(%rbp)
jbe 0x1c21ce
movq -0x88(%rbp), %rdi
movq -0x88(%rbp), %rsi
movq 0x20(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rsi
callq 0x1be4b0
movq $0x0, -0x40(%rbp)
movq $0x0, -0x38(%rbp)
movq $0x1, -0x50(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x50(%rbp), %rax
cmpq 0x20(%rbp), %rax
ja 0x1c22ff
movq -0x50(%rbp), %rax
cmpq 0x20(%rbp), %rax
je 0x1c2238
movq -0x88(%rbp), %rax
movq -0x50(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq -0x88(%rbp), %rcx
movq -0x48(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
cmpq 0x8(%rcx), %rax
je 0x1c22ec
movq -0x38(%rbp), %rax
shrq $0x20, %rax
movq -0x88(%rbp), %rcx
movq -0x48(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movq 0x8(%rcx), %rcx
shrq $0x20, %rcx
cmpq %rcx, %rax
jae 0x1c2287
movq -0x88(%rbp), %rax
movq -0x48(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x50(%rbp), %rax
subq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0x1c22e4
movq -0x38(%rbp), %rax
shrq $0x20, %rax
movq -0x88(%rbp), %rcx
movq -0x48(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movq 0x8(%rcx), %rcx
shrq $0x20, %rcx
cmpq %rcx, %rax
jne 0x1c22e2
movq -0x50(%rbp), %rax
subq -0x48(%rbp), %rax
cmpq -0x40(%rbp), %rax
jbe 0x1c22e2
movq -0x88(%rbp), %rax
movq -0x48(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x50(%rbp), %rax
subq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0x1c22e4
movq -0x50(%rbp), %rax
movq %rax, -0x48(%rbp)
jmp 0x1c22ee
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
jmp 0x1c21ee
movq 0x20(%rbp), %rdx
movq -0x30(%rbp), %rax
movq (%rax), %rcx
subq %rdx, %rcx
movq %rcx, (%rax)
movq $0x0, -0x58(%rbp)
movq $0x0, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpq 0x20(%rbp), %rax
jae 0x1c2394
movq -0x88(%rbp), %rax
movq -0x50(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
cmpq -0x38(%rbp), %rax
jne 0x1c2384
movq -0x88(%rbp), %rcx
movq -0x50(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rcx
movq -0x88(%rbp), %rax
movq -0x58(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x1c2386
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
jmp 0x1c2320
movq -0x58(%rbp), %rax
movq %rax, 0x20(%rbp)
movq 0x20(%rbp), %rcx
movq -0x30(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movq -0x38(%rbp), %rax
addq $0xb0, %rsp
popq %rbp
retq
nopw (%rax,%rax)