// File: 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
movq %rsp, %rbp
subq $0x1d0, %rsp            # imm = 0x1D0
movb %cl, %al
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
andb $0x1, %al
movb %al, -0x21(%rbp)
movq -0x10(%rbp), %rdi
callq 0xe480
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rdi
callq 0xe480
movq %rax, -0x38(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xe8d0
movq $-0x1, -0x60(%rbp)
movq $-0x1, -0x68(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x12fe0
movq -0x30(%rbp), %rax
movq -0x20(%rbp), %rcx
addq $0x1, %rcx
cqto
idivq %rcx
movl %eax, -0x84(%rbp)
testb $0x1, -0x21(%rbp)
je 0xfbf1
movq 0x82426(%rip), %rdi     # 0x91f78
leaq 0x51671(%rip), %rsi     # 0x611ca
callq 0xe610
movq %rax, -0x118(%rbp)
jmp 0xfb67
movq -0x118(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0xe580
movq %rax, -0x120(%rbp)
jmp 0xfb80
movq -0x120(%rbp), %rdi
movl $0xa, %esi
callq 0xe780
movq %rax, -0x128(%rbp)
jmp 0xfb9a
movq -0x128(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xe580
movq %rax, -0x130(%rbp)
jmp 0xfbb3
movq -0x130(%rbp), %rdi
movl $0xa, %esi
callq 0xe780
jmp 0xfbc6
jmp 0xfbf1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x131e0
leaq -0x58(%rbp), %rdi
callq 0xe400
jmp 0x10008
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x84(%rbp), %edx
callq 0xf410
movb %al, -0x131(%rbp)
jmp 0xfc0c
movb -0x131(%rbp), %al
testb $0x1, %al
jne 0xfcc0
jmp 0xfc1c
testb $0x1, -0x21(%rbp)
je 0xfca9
movq 0x8234b(%rip), %rdi     # 0x91f78
leaq 0x5159f(%rip), %rsi     # 0x611d3
callq 0xe610
movq %rax, -0x140(%rbp)
jmp 0xfc42
movq -0x140(%rbp), %rdi
movl -0x84(%rbp), %esi
callq 0xeb40
movq %rax, -0x148(%rbp)
jmp 0xfc5d
movq -0x148(%rbp), %rdi
leaq 0x5158c(%rip), %rsi     # 0x611f7
callq 0xe610
movq %rax, -0x150(%rbp)
jmp 0xfc79
movq -0x150(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xe360
movq %rax, -0x158(%rbp)
jmp 0xfc92
movq -0x158(%rbp), %rdi
leaq 0x5187a(%rip), %rsi     # 0x6151a
callq 0xe610
jmp 0xfca7
jmp 0xfca9
movq -0x68(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x98(%rbp)
jmp 0xffe9
movq $0x0, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
cmpq -0x38(%rbp), %rax
jge 0xfe8f
movq -0x18(%rbp), %rsi
movq -0xa0(%rbp), %rdx
movq -0x30(%rbp), %rcx
leaq -0xc0(%rbp), %rdi
callq 0xe670
jmp 0xfcf9
leaq -0x58(%rbp), %rdi
movq %rdi, -0x168(%rbp)
leaq -0xc0(%rbp), %rsi
movq %rsi, -0x170(%rbp)
callq 0xe7d0
movq -0x170(%rbp), %rdi
callq 0xe400
movq -0x168(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0xf610
movq %rax, -0x160(%rbp)
jmp 0xfd40
movq -0x160(%rbp), %rax
movq %rax, -0x60(%rbp)
testb $0x1, -0x21(%rbp)
je 0xfe3f
movq 0x8221c(%rip), %rdi     # 0x91f78
leaq 0x514cf(%rip), %rsi     # 0x61232
callq 0xe610
movq %rax, -0x178(%rbp)
jmp 0xfd71
movq -0x178(%rbp), %rdi
movq -0xa0(%rbp), %rsi
callq 0xe360
movq %rax, -0x180(%rbp)
jmp 0xfd8d
movq -0x180(%rbp), %rdi
leaq 0x514a4(%rip), %rsi     # 0x6123f
callq 0xe610
movq %rax, -0x188(%rbp)
jmp 0xfda9
movq -0x188(%rbp), %rdi
movq -0x60(%rbp), %rsi
callq 0xe360
movq %rax, -0x190(%rbp)
jmp 0xfdc2
movq -0x190(%rbp), %rdi
leaq 0x5147a(%rip), %rsi     # 0x6124a
callq 0xe610
movq %rax, -0x198(%rbp)
jmp 0xfdde
movq -0x198(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0xe580
movq %rax, -0x1a0(%rbp)
jmp 0xfdf7
movq -0x1a0(%rbp), %rdi
movl $0xa, %esi
callq 0xe780
movq %rax, -0x1a8(%rbp)
jmp 0xfe11
movq -0x1a8(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0xe580
movq %rax, -0x1b0(%rbp)
jmp 0xfe2a
movq -0x1b0(%rbp), %rdi
movl $0xa, %esi
callq 0xe780
jmp 0xfe3d
jmp 0xfe3f
movq -0x60(%rbp), %rax
cmpq -0x20(%rbp), %rax
jg 0xfe76
leaq -0xd0(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0xa0(%rbp), %rdx
callq 0x13030
jmp 0xfe62
leaq -0x80(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x13000
jmp 0xfe74
jmp 0xfe76
jmp 0xfe78
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0xfccb
leaq -0x80(%rbp), %rdi
movq %rdi, -0x1b8(%rbp)
callq 0x130a0
movq -0x1b8(%rbp), %rdi
movq %rax, -0xd8(%rbp)
callq 0x130d0
movq %rax, -0xe0(%rbp)
movq -0xd8(%rbp), %rdi
movq -0xe0(%rbp), %rsi
callq 0x13060
jmp 0xfece
testb $0x1, -0x21(%rbp)
je 0xffb5
leaq -0x80(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rdi
callq 0x130a0
movq %rax, -0xf0(%rbp)
movq -0xe8(%rbp), %rdi
callq 0x130d0
movq %rax, -0xf8(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x13100
testb $0x1, %al
jne 0xff25
jmp 0xffb3
leaq -0xf0(%rbp), %rdi
callq 0x13140
movups (%rax), %xmm0
movaps %xmm0, -0x110(%rbp)
movq -0x110(%rbp), %rsi
movq 0x8202f(%rip), %rdi     # 0x91f78
callq 0xe360
movq %rax, -0x1c0(%rbp)
jmp 0xff57
movq -0x1c0(%rbp), %rdi
movl $0x3a, %esi
callq 0xe780
movq %rax, -0x1c8(%rbp)
jmp 0xff71
movq -0x1c8(%rbp), %rdi
movq -0x108(%rbp), %rsi
callq 0xe360
movq %rax, -0x1d0(%rbp)
jmp 0xff8d
movq -0x1d0(%rbp), %rdi
movl $0xa, %esi
callq 0xe780
jmp 0xffa0
jmp 0xffa2
leaq -0xf0(%rbp), %rdi
callq 0x13160
jmp 0xff09
jmp 0xffb5
leaq -0x80(%rbp), %rdi
callq 0x13180
testb $0x1, %al
jne 0xffd7
leaq -0x80(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x131c0
movq 0x8(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x98(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x131e0
leaq -0x58(%rbp), %rdi
callq 0xe400
movq -0x8(%rbp), %rax
addq $0x1d0, %rsp            # imm = 0x1D0
popq %rbp
retq
movq -0x90(%rbp), %rdi
callq 0xeb80
nopw %cs:(%rax,%rax)