// File: /workspace/github_cpp_makefile_star2_O2/ParkerLab[P]cta/src/cta.cpp
// Function: align(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, long long, bool)
long long int align(const std::string& seq1, const std::string& seq2, long long int max_edit_distance, bool verbose = false) {
    long long int seq1_length = seq1.size();
    long long int seq2_length = seq2.size();
    std::string window;
    long long int distance = -1;
    long long int best_position = -1;
    std::vector<std::pair<long long int, long long int>> alignments;

    int min_shared_kmer_size = seq1_length / (max_edit_distance + 1); // For two strings to have edit distance <= max_edit_distance, they must share a kmer of at least this size

    if (verbose) {
        std::cout << "align: \n" << seq1 << '\n' << seq2 << '\n';
    }

    if (!shares_kmer(seq1, seq2, min_shared_kmer_size)) {
        if (verbose) {
            std::cout << "align: no shared kmer of length >= " << min_shared_kmer_size << " between these sequences, so cannot have edit distance <= " << max_edit_distance << "\n";
        }
        return best_position;
    }

    for (long long int i = 0; i < seq2_length; i++) {
        window = seq2.substr(i, seq1_length);
        distance = levenshtein_distance(window, seq1, max_edit_distance);

        if (verbose) {
            std::cout << "at position " << i << " distance " << distance << " between\n" << seq1 << '\n' << window << '\n';
        }

        if (distance <= max_edit_distance) {
            alignments.push_back(std::pair<long long int, long long int>(distance, i));
        }
    }

    std::sort(alignments.begin(), alignments.end());
    if (verbose) {
        for (auto it : alignments ) {
            std::cout << it.first << ':' << it.second << '\n';
        }
    }

    if (!alignments.empty()) {
        best_position = alignments[0].second;
    }

    return best_position;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdx, %rbx
movq %rdi, %r15
movq 0x8(%rdi), %rax
movq %rsi, 0x8(%rsp)
movq 0x8(%rsi), %r12
leaq 0x48(%rsp), %rdx
movq %rdx, -0x10(%rdx)
andq $0x0, -0x8(%rdx)
movb $0x0, (%rdx)
andq $0x0, 0x20(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
leaq 0x1(%rbx), %rsi
movq %rax, 0x30(%rsp)
cqto
idivq %rsi
movq %rax, %r14
movl %ecx, 0x4(%rsp)
testl %ecx, %ecx
je 0xd14d
movq 0x31e65(%rip), %rdi     # 0x3ef78
leaq 0x19070(%rip), %rsi     # 0x2618a
callq 0xc490
movq %rax, %rdi
movq %r15, %rsi
callq 0xc430
pushq $0xa
popq %rsi
movq %rax, %rdi
callq 0xc590
movq %rax, %rdi
movq 0x8(%rsp), %rsi
callq 0xc430
pushq $0xa
popq %rsi
movq %rax, %rdi
callq 0xc590
movq %r15, %rdi
movq 0x8(%rsp), %rsi
movl %r14d, %edx
callq 0xcdd1
testb %al, %al
je 0xd260
xorl %r13d, %r13d
testq %r12, %r12
cmovleq %r13, %r12
movq %r12, 0x28(%rsp)
leaq 0x58(%rsp), %rbp
leaq 0x38(%rsp), %r12
cmpq %r13, 0x28(%rsp)
je 0xd2bb
movq %rbp, %rdi
movq 0x8(%rsp), %rsi
movq %r13, %rdx
movq 0x30(%rsp), %rcx
callq 0xc500
movq %r12, %rdi
movq %rbp, %rsi
callq 0xc5d0
movq %rbp, %rdi
callq 0xc250
movq %r12, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0xced8
movq %rax, %r14
cmpb $0x0, 0x4(%rsp)
je 0xd23c
movq 0x31da8(%rip), %rdi     # 0x3ef78
leaq 0x1901b(%rip), %rsi     # 0x261f2
callq 0xc490
movq %rax, %rdi
movq %r13, %rsi
callq 0xc1d0
movq %rax, %rdi
leaq 0x1900e(%rip), %rsi     # 0x261ff
callq 0xc490
movq %rax, %rdi
movq %r14, %rsi
callq 0xc1d0
movq %rax, %rdi
leaq 0x18fff(%rip), %rsi     # 0x2620a
callq 0xc490
movq %rax, %rdi
movq %r15, %rsi
callq 0xc430
movq %rax, %rdi
pushq $0xa
popq %rsi
callq 0xc590
movq %rax, %rdi
movq %r12, %rsi
callq 0xc430
movq %rax, %rdi
pushq $0xa
popq %rsi
callq 0xc590
cmpq %rbx, %r14
jg 0xd258
movq %r14, 0x58(%rsp)
movq %r13, 0x60(%rsp)
leaq 0x10(%rsp), %rdi
movq %rbp, %rsi
callq 0x1d160
incq %r13
jmp 0xd17e
pushq $-0x1
popq %r15
cmpb $0x0, 0x4(%rsp)
je 0xd33f
movq 0x31d02(%rip), %rdi     # 0x3ef78
leaq 0x18f16(%rip), %rsi     # 0x26193
callq 0xc490
movq %rax, %rdi
movl %r14d, %esi
callq 0xc7f0
leaq 0x18f23(%rip), %rsi     # 0x261b7
movq %rax, %rdi
callq 0xc490
movq %rax, %rdi
movq %rbx, %rsi
callq 0xc1d0
leaq 0x1922c(%rip), %rsi     # 0x264da
movq %rax, %rdi
callq 0xc490
jmp 0xd33f
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rsi
callq 0x1d2df
movq 0x10(%rsp), %r12
movq 0x18(%rsp), %r13
cmpb $0x0, 0x4(%rsp)
je 0xd32f
movq 0x31c96(%rip), %rbx     # 0x3ef78
pushq $0x3a
popq %rbp
pushq $0xa
popq %r14
cmpq %r13, %r12
je 0xd325
movq (%r12), %rsi
movq 0x8(%r12), %r15
movq %rbx, %rdi
callq 0xc1d0
movq %rax, %rdi
movl %ebp, %esi
callq 0xc590
movq %rax, %rdi
movq %r15, %rsi
callq 0xc1d0
movq %rax, %rdi
movl %r14d, %esi
callq 0xc590
addq $0x10, %r12
jmp 0xd2e9
movq 0x10(%rsp), %r12
movq 0x18(%rsp), %r13
cmpq %r13, %r12
je 0xd33b
movq 0x8(%r12), %r15
jmp 0xd33f
pushq $-0x1
popq %r15
leaq 0x10(%rsp), %rdi
callq 0x1d12c
leaq 0x38(%rsp), %rdi
callq 0xc250
movq %r15, %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xd36d
jmp 0xd36d
jmp 0xd36d
jmp 0xd36d
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x1d12c
leaq 0x38(%rsp), %rdi
callq 0xc250
movq %rbx, %rdi
callq 0xc820