// File: medvedevgroup[P]varmatch/src/wholegenome.cpp
// Function: WholeGenome::PathExtendOneStep(SequencePath&, std::multimap<int, int, std::less<int>, std::allocator<std::pair<int const, int>>>**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<int, std::allocator<int>>&, int, int&)
int WholeGenome::PathExtendOneStep(SequencePath& sp,
                                   multimap<int, int> * choices_by_pos[],
                                   const string & reference_sequence,
                                   vector<int> & sync_points,
                                   int match_mode,
                                   int & variant_need_decision){
    //-1 operation fail, path deleted
    //0 operation succeed
    //1 operation fail, need to make decision first, then extend
    //2 path reached end, need to check if good

    if(sp.reached_sync_num >= sync_points.size()) return -1;

    int start_pos = sp.current_genome_pos + 1;
    int end_pos = sync_points[sp.reached_sync_num]; // the next sync point, end pos included

    for(int next_genome_pos = start_pos; next_genome_pos <= end_pos; next_genome_pos++){

        // before make decision, we need to check if the equal property still holds
        int variant_need_decision_ = PathNeedDecision(sp, choices_by_pos, next_genome_pos);
        if(variant_need_decision_ >= 0){

            // check equal property
            int statu = CheckPathEqualProperty(sp, match_mode);
            if(statu == -1) return -1;
            variant_need_decision = variant_need_decision_;
            return 1; // need decision on next position
        }

        // else extend one nt
        for(int i = 0; i < 4; i++){

            if(match_mode == 1){
                if(i%2 != 0) continue;
            }

            if(sp.string_sequences[i][next_genome_pos] == "."){
                sp.donor_sequences[i] += reference_sequence[next_genome_pos];
            }else{
                sp.donor_sequences[i] += sp.string_sequences[i][next_genome_pos];
            }
        }
        sp.current_genome_pos = next_genome_pos;
    }

    // reaches the end of end_pos
    sp.reached_sync_num ++;

    if(sp.reached_sync_num >= sync_points.size()){
        // last sync point is the end of ref genome sequence
        if(sp.donor_sequences[0] == sp.donor_sequences[2] &&
           sp.donor_sequences[1] == sp.donor_sequences[3]){
            return 2;
       }else{
            //dout << "delete this path at pos: " << sp.current_genome_pos << " for reach end but not equal";
            //PrintPath(sp);
            return -1;
       }
    }
    return CheckPathEqualProperty(sp, match_mode);
    // first try to converge, then extend

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movl %r9d, -0x34(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x18(%rbp), %rax
movslq 0x160(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x30(%rbp), %rdi
callq 0x19a40
movq %rax, %rcx
movq -0x58(%rbp), %rax
cmpq %rcx, %rax
jb 0x21d8c
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x21fbb
movq -0x18(%rbp), %rax
movl 0xc8(%rax), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
movq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rax
movslq 0x160(%rax), %rsi
callq 0x19a60
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0x38(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jg 0x21f11
movq -0x60(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl -0x40(%rbp), %ecx
callq 0x217a0
movl %eax, -0x44(%rbp)
cmpl $0x0, -0x44(%rbp)
jl 0x21e1e
movq -0x60(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x34(%rbp), %edx
callq 0x218c0
movl %eax, -0x48(%rbp)
cmpl $-0x1, -0x48(%rbp)
jne 0x21e09
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x21fbb
movl -0x44(%rbp), %ecx
movq 0x10(%rbp), %rax
movl %ecx, (%rax)
movl $0x1, -0x4(%rbp)
jmp 0x21fbb
movl $0x0, -0x4c(%rbp)
cmpl $0x4, -0x4c(%rbp)
jge 0x21ef6
cmpl $0x1, -0x34(%rbp)
jne 0x21e4c
movl -0x4c(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x21e4a
jmp 0x21ee8
jmp 0x21e4c
movq -0x18(%rbp), %rdi
addq $0x8, %rdi
movslq -0x4c(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x40(%rbp), %rsi
callq 0x9080
movq %rax, %rdi
leaq 0x33bc0(%rip), %rsi     # 0x55a32
callq 0x125e0
testb $0x1, %al
jne 0x21e7d
jmp 0x21eac
movq -0x28(%rbp), %rdi
movslq -0x40(%rbp), %rsi
callq 0x64d0
movb (%rax), %al
movq -0x18(%rbp), %rdi
addq $0xd0, %rdi
movslq -0x4c(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rdi
movsbl %al, %esi
callq 0x62b0
jmp 0x21ee6
movq -0x18(%rbp), %rdi
addq $0x8, %rdi
movslq -0x4c(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x40(%rbp), %rsi
callq 0x9080
movq %rax, %rsi
movq -0x18(%rbp), %rdi
addq $0xd0, %rdi
movslq -0x4c(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x6560
jmp 0x21ee8
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x21e25
movl -0x40(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0xc8(%rax)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x21dbb
movq -0x18(%rbp), %rax
movl 0x160(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x160(%rax)
movq -0x18(%rbp), %rax
movslq 0x160(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x30(%rbp), %rdi
callq 0x19a40
movq %rax, %rcx
movq -0x68(%rbp), %rax
cmpq %rcx, %rax
jb 0x21fa8
movq -0x18(%rbp), %rdi
addq $0xd0, %rdi
movq -0x18(%rbp), %rsi
addq $0xd0, %rsi
addq $0x40, %rsi
callq 0xdcb0
testb $0x1, %al
jne 0x21f6d
jmp 0x21f9f
movq -0x18(%rbp), %rdi
addq $0xd0, %rdi
addq $0x20, %rdi
movq -0x18(%rbp), %rsi
addq $0xd0, %rsi
addq $0x60, %rsi
callq 0xdcb0
testb $0x1, %al
jne 0x21f96
jmp 0x21f9f
movl $0x2, -0x4(%rbp)
jmp 0x21fbb
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x21fbb
movq -0x60(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x34(%rbp), %edx
callq 0x218c0
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)