// File: chhylp123[P]hifiasm/hic.cpp
// Function: hic_short_align(enzyme const*, enzyme const*, ha_ug_index*, ug_opt_t*, kvec_pe_hit**)
int hic_short_align(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits)
{
    double index_time = yak_realtime();
    sldat_t sl;
    sl.idx = idx;
    sl.t_ch = idx->t_ch;
    sl.chunk_size = 20000000;
    sl.n_thread = asm_opt.thread_num;
    sl.total_base = sl.total_pair = 0;
    idx->hap_cnt = asm_opt.hap_occ;
    kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ);


    if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name))
    {
        alignment_worker_pipeline(&sl, fn1, fn2);
        write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name);
    }
    sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode;

    /***debug***/
    if(sl.hits.idx.n == 0) idx_hc_links(&(sl.hits), idx, NULL);
    // optimize_u_trans(&(idx->t_ch->k_trans), &sl.hits, idx);
    // filter_kv_u_trans_t(&(idx->t_ch->k_trans), idx->ug, 0.5);
    /***debug***/
    
    // print_kv_u_trans_t(&(idx->t_ch->k_trans), idx->ug);
    // flter_by_cov(idx, &sl.hits, 2);
    // update_hits(idx, &sl.hits, idx->t_ch->is_r_het);
    ///debug_hc_hits_v14(&sl.hits, asm_opt.output_file_name, sl.idx);
    ////dedup_hits(&(sl.hits), sl.idx);   
    ///write_hc_hits_v14(&sl.hits, asm_opt.output_file_name);
    
    if(asm_opt.misjoin_len > 0/** && (!(asm_opt.ar))**/)//disable it for the UL assembly
    {
        update_switch_unitig(idx->ug, idx->read_g, &(sl.hits), &(idx->t_ch->k_trans), 10, 20, asm_opt.misjoin_len, 0.15);
        renew_idx_para(idx, idx->ug);
    }
    // print_hits_simp(idx, &sl.hits);
    // print_kv_u_trans_t(&(idx->t_ch->k_trans));

    hc_links link;
    init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch);
    ///H_partition hap;
    bubble_type bub; 
    kv_u_trans_t k_trans; 
    kv_init(k_trans); kv_init(k_trans.idx);
    ps_t *s = NULL;
    mb_nodes_t u; 
    kv_init(u.bid); kv_init(u.idx); kv_init(u.u);
    memset(&bub, 0, sizeof(bubble_type));
    bub.round_id = 0; bub.n_round = asm_opt.n_weight;

    resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans);
    measure_distance(idx, idx->ug, &sl.hits, &link, &bub, &(idx->t_ch->k_trans));
    // if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_ps_t(&s, asm_opt.output_file_name))
    // {
    //     bub.round_id = bub.n_round;
    //     label_unitigs_sm(s->s, NULL, idx->ug);
    //     goto skip_flipping;
    // }
    // print_debug_gfa(idx->read_g, idx->ug, opt->coverage_cut, "hic.phasing", opt->sources, opt->ruIndex, 
    // opt->max_hang, opt->min_ovlp, 0, 0, 0);
    
    s = init_ps_t(11, idx->ug->g->n_seq);
    // debug_round_test(s, 11, &bub, &k_trans, &link, &sl, idx, 1000, 10000);
    for (bub.round_id = 0; bub.round_id < bub.n_round; bub.round_id++)
    {
        // identify_bubbles(idx->ug, &bub, idx->t_ch->is_r_het, &(idx->t_ch->k_trans));
        renew_kv_u_trans(&k_trans, &link, &sl.hits, &(idx->t_ch->k_trans), idx, &bub, s->s, NULL, 0);
        // if(bub.round_id == 0) init_phase(idx, &k_trans, &bub, s); 
        // update_trans_g(idx, &k_trans, &bub);
        /*******************************for debug************************************/
        mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, 
        (bub.round_id == 0? 1 : 0), s->s, 1, &bub, 
        &(idx->t_ch->k_trans), 0, /**(((bub.round_id+1) == bub.n_round)?1:0)**/0);
        // mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, 
        // (bub.round_id == 0? 1 : 0), s->s, 1, NULL, &(idx->t_ch->k_trans), 0, 0);
        /**
        if((bub.round_id+1) == bub.n_round) {
            prt_debug_hic(asm_opt.output_file_name, idx->ug, idx, opt, &sl.hits, 
            &(idx->t_ch->k_trans), &k_trans, &link, s->s, &(bub));
        }
        **/
        /*******************************for debug************************************/
        label_unitigs_sm(s->s, NULL, idx->ug);

        /*******************************for debug************************************/
        // if(bub.round_id == bub.n_round - 1)
        // {
        //     debug_output_disconnected_hits(idx, &k_trans, &sl.hits, &link, &bub, s->s);
        // }
        /*******************************for debug************************************/
        /**
        init_hic_advance((ha_ug_index*)sl.idx, &sl.hits, &link, &bub, &hap, 0);
        reset_H_partition(&hap, (bub.round_id == 0? 1 : 0));
        init_contig_partition(&hap, idx, &bub, &link);
        phasing_improvement(&hap, &(hap.g_p), idx, &bub, &link);
        label_unitigs(&(hap.g_p), idx->ug);
        **/
    }
    // write_ps_t(s, asm_opt.output_file_name);
    // skip_flipping:
    verbose_het_stat(&bub);

    if(rhits) (*rhits) = get_r_hits_order(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub);

    // tag_reads(idx, &sl.hits, &bub, s->s, opt->sources);

    // print_kv_weight(&k_trans, s->s);

    // horder_t *ho = init_horder_t(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, &(idx->t_ch->k_trans), opt, 3);

    // print_hc_links(&link, 0, &hap);
    // print_hits_simp(idx, &sl.hits);
    // print_kv_u_trans_t(&(idx->t_ch->k_trans));
    // print_kv_u_trans(&k_trans, &link, s->s);
    // print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, NULL/**idx->link**/, idx);
    // print_hits(idx, &sl.hits, fn1, fn2);
    // print_debug_bubble_graph(&bub, idx->ug, asm_opt.output_file_name);
    // print_bubble_chain(&bub);

    // destory_contig_partition(&hap);
    // destory_horder_t(&ho);
    kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ);
    destory_hc_links(&link);
    kv_destroy(k_trans); kv_destroy(k_trans.idx);
    destory_ps_t(&s);
    kv_destroy(u.bid); kv_destroy(u.idx); kv_destroy(u.u);
    destory_bubbles(&bub);
    return 1;
    

    print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, &link, idx);
    collect_hc_reverse_links(&link, idx->ug, &bub);
    normalize_hc_links(&link);
    min_cut_t* cut = clean_hap(&link, &bub, idx->ug);
    ///print_bubbles(idx->ug, &bub, NULL, &link, idx);
    G_partition* gp = clean_bubbles(&link, &bub, cut, idx->ug);
    ///print_hc_links(&link);
    destory_min_cut_t(cut); free(cut);
    destory_G_partition(gp); free(gp);
    destory_bubbles(&bub);
    
    fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base);
    return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
subq $0x2d8, %rsp            # imm = 0x2D8
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
callq 0x1b7ca0
movsd %xmm0, -0x38(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
movq $0x1312d00, -0xb8(%rbp) # imm = 0x1312D00
leaq 0x1bac95(%rip), %rax    # 0x3c47f8
movslq 0x7c(%rax), %rax
movq %rax, -0xb0(%rbp)
movq $0x0, -0xa0(%rbp)
movq $0x0, -0xa8(%rbp)
leaq 0x1bac6d(%rip), %rax    # 0x3c47f8
movslq 0x1b8(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x48(%rax)
movq $0x0, -0x90(%rbp)
movq $0x0, -0x98(%rbp)
movq $0x0, -0x88(%rbp)
movq $0x0, -0x78(%rbp)
movq $0x0, -0x80(%rbp)
movq $0x0, -0x70(%rbp)
movq $0x0, -0x60(%rbp)
movq $0x0, -0x68(%rbp)
movq $0x0, -0x58(%rbp)
leaq -0xd0(%rbp), %rdi
addq $0x38, %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rsi
leaq 0x1babf4(%rip), %rax    # 0x3c47f8
movq 0x10(%rax), %rdx
callq 0x1d5990
cmpl $0x0, %eax
jne 0x209c48
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
leaq -0xd0(%rbp), %rdi
callq 0x200e50
leaq -0xd0(%rbp), %rdi
addq $0x38, %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rsi
leaq 0x1babb9(%rip), %rax    # 0x3c47f8
movq 0x10(%rax), %rdx
callq 0x1d44d0
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x80(%rbp)
jne 0x209c7f
leaq -0xd0(%rbp), %rdi
addq $0x38, %rdi
movq -0x20(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x1d2bc0
leaq 0x1bab72(%rip), %rax    # 0x3c47f8
cmpq $0x0, 0x1e8(%rax)
jbe 0x209cf4
movq -0x20(%rbp), %rax
movq (%rax), %rdi
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rsi
leaq -0xd0(%rbp), %rdx
addq $0x38, %rdx
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rcx
addq $0x138, %rcx            # imm = 0x138
leaq 0x1bab38(%rip), %rax    # 0x3c47f8
movq 0x1e8(%rax), %rax
movl $0xa, %r8d
movl $0x14, %r9d
movsd 0x17856d(%rip), %xmm0   # 0x382248
movq %rax, (%rsp)
callq 0x23c580
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rsi
callq 0x207e90
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq 0x18(%rax), %rax
movl 0x14(%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, %eax
movl %eax, %esi
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rdx
leaq -0x100(%rbp), %rdi
callq 0xfca90
movq $0x0, -0x238(%rbp)
movq $0x0, -0x240(%rbp)
movq $0x0, -0x230(%rbp)
movq $0x0, -0x220(%rbp)
movq $0x0, -0x228(%rbp)
movq $0x0, -0x218(%rbp)
movq $0x0, -0x248(%rbp)
movq $0x0, -0x288(%rbp)
movq $0x0, -0x290(%rbp)
movq $0x0, -0x280(%rbp)
movq $0x0, -0x270(%rbp)
movq $0x0, -0x278(%rbp)
movq $0x0, -0x268(%rbp)
movq $0x0, -0x258(%rbp)
movq $0x0, -0x260(%rbp)
movq $0x0, -0x250(%rbp)
leaq -0x210(%rbp), %rdi
xorl %esi, %esi
movl $0x110, %edx            # imm = 0x110
callq 0x2100
movl $0x0, -0x208(%rbp)
leaq 0x1baa05(%rip), %rax    # 0x3c47f8
movl 0x1e0(%rax), %eax
movl %eax, -0x204(%rbp)
movq -0x20(%rbp), %rdi
leaq -0xd0(%rbp), %rdx
addq $0x38, %rdx
leaq -0x210(%rbp), %rsi
leaq -0x240(%rbp), %rcx
callq 0x205720
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rsi
leaq -0xd0(%rbp), %rdx
addq $0x38, %rdx
movq -0x20(%rbp), %rax
movq 0x10(%rax), %r9
addq $0x138, %r9             # imm = 0x138
leaq -0x100(%rbp), %rcx
leaq -0x210(%rbp), %r8
callq 0x1d30a0
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq 0x18(%rax), %rax
movl 0x14(%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, %eax
movl %eax, %esi
movl $0xb, %edi
callq 0x204880
movq %rax, -0x248(%rbp)
movl $0x0, -0x208(%rbp)
movl -0x208(%rbp), %eax
cmpl -0x204(%rbp), %eax
jae 0x209fbb
leaq -0xd0(%rbp), %rdx
addq $0x38, %rdx
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rcx
addq $0x138, %rcx            # imm = 0x138
movq -0x20(%rbp), %r8
movq -0x248(%rbp), %rax
movq (%rax), %rax
leaq -0x240(%rbp), %rdi
leaq -0x100(%rbp), %rsi
leaq -0x210(%rbp), %r9
xorl %r10d, %r10d
xorl %r10d, %r10d
movq %rax, (%rsp)
movq $0x0, 0x8(%rsp)
movl $0x0, 0x10(%rsp)
callq 0x2043f0
movq -0x20(%rbp), %rax
movq (%rax), %rcx
movq -0x20(%rbp), %rax
movq 0x8(%rax), %r8
leaq 0x1bb3c0(%rip), %rax    # 0x3c52d0
movq 0x28(%rax), %r9
movl -0x208(%rbp), %edx
xorl %ebx, %ebx
movl $0x1, %eax
cmpl $0x0, %edx
cmovel %eax, %ebx
movq -0x248(%rbp), %rax
movq (%rax), %r11
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
addq $0x138, %rax            # imm = 0x138
xorl %edx, %edx
movl %edx, %esi
leaq -0x240(%rbp), %rdx
movsd 0x1782de(%rip), %xmm0   # 0x382230
leaq -0x210(%rbp), %r10
xorl %edi, %edi
movq %rsi, %rdi
movl %ebx, (%rsp)
movq %r11, 0x8(%rsp)
movl $0x1, 0x10(%rsp)
movq %r10, 0x18(%rsp)
movq %rax, 0x20(%rsp)
movl $0x0, 0x28(%rsp)
movl $0x0, 0x30(%rsp)
callq 0x227770
movq -0x248(%rbp), %rax
movq (%rax), %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rdx
xorl %eax, %eax
movl %eax, %esi
callq 0x1ff3d0
movl -0x208(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x208(%rbp)
jmp 0x209e8b
leaq -0x210(%rbp), %rdi
callq 0x204f60
cmpq $0x0, -0x30(%rbp)
je 0x20a00e
leaq -0xd0(%rbp), %rdi
addq $0x38, %rdi
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x20(%rbp), %rax
movq (%rax), %r8
leaq -0x210(%rbp), %r9
callq 0x249ec0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movq -0x88(%rbp), %rdi
callq 0x2210
movq -0x70(%rbp), %rdi
callq 0x2210
movq -0x58(%rbp), %rdi
callq 0x2210
leaq -0x100(%rbp), %rdi
callq 0xfcce0
movq -0x230(%rbp), %rdi
callq 0x2210
movq -0x218(%rbp), %rdi
callq 0x2210
leaq -0x248(%rbp), %rdi
callq 0x2048f0
movq -0x280(%rbp), %rdi
callq 0x2210
movq -0x268(%rbp), %rdi
callq 0x2210
movq -0x250(%rbp), %rdi
callq 0x2210
leaq -0x210(%rbp), %rdi
callq 0x1c4a90
movl $0x1, %eax
addq $0x2d8, %rsp            # imm = 0x2D8
popq %rbx
popq %rbp
retq
nopl (%rax,%rax)