// File: prophyle[P]prophasm/src/prophasm.cpp
// Function: int assemble<std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>&, int, _IO_FILE*, bool)
int assemble(const std::string &fasta_fn, _set_T &set, int32_t k, FILE* fstats, bool verbose){
	if(fstats){
		fprintf(fstats,"%s\t%lu\n",fasta_fn.c_str(),set.size());
	}

	FILE *file=nullptr;
	if(fasta_fn=="-"){
		file=stdout;
	}
	else{
		file=fopen(fasta_fn.c_str(),"w+");
		test_file(file, fasta_fn);
	}
	char kmer_str[max_allowed_kmer_length+1];
	contig_t contig(k);
	const std::vector<char> nucls = {'A','C','G','T'};

	//int32_t i=0;
	int32_t contig_id=1;
	while(set.size()>0){

		const auto central_nkmer=*(set.begin());
		set.erase(central_nkmer);

		std::string central_kmer_string;
		decode_kmer(central_nkmer,k,central_kmer_string);
		contig.new_contig(central_kmer_string.c_str());

		typename _set_T::value_type nkmer;


		for (int direction=0;direction<2;direction++){

			//std::cerr << "direction " << direction << std::endl;

			if (direction==0){
				// forward
			}
			else{
				// reverse
				reverse_complement_in_place(central_kmer_string);
			}

			strncpy(kmer_str,central_kmer_string.c_str(),k);
			kmer_str[k]='\0';

			bool extending = true;

			//std::cerr << "central k-mer: " << central_kmer_string << std::endl;


			while (extending){
				for(int32_t i=0;i<k;i++){
					kmer_str[i]=kmer_str[i+1];
				}
				kmer_str[k]='\0';

				extending=false;
				for(const char &c : nucls){
					kmer_str[k-1]=c;

					encode_canonical(kmer_str, k, nkmer);

					if(set.count( nkmer )){
						//std::cerr << "extending " << c << std::endl;
						//debug_print_kmer_set(set,k);
						//std::cerr << std::string(contig.l_ext) << c << std::endl;
						//std::cerr << std::endl;
						if(direction==0){
							contig.r_extend(c);
						}
						else{
							contig.l_extend(c);
						}
						set.erase(nkmer);

						if(!contig.is_full()){
							extending=true;
						}
						break;
					}
				}
			}
		}

		//std::cerr << "====================" << std::endl;

		std::stringstream ss;
		ss<<"c"<<contig_id;
		const std::string contig_name(ss.str());
		contig.print_to_fasta(file,contig_name.c_str());
		contig_id++;
	}

	fclose(file);

	if(verbose){
		std::cerr << "   assembly finished (" << contig_id << " contigs)" << std::endl;
	}

	return 0;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x370, %rsp            # imm = 0x370
movb %r8b, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
andb $0x1, %al
movb %al, -0x21(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x5d5c
movq -0x20(%rbp), %rax
movq %rax, -0x308(%rbp)
movq -0x8(%rbp), %rdi
callq 0x30e0
movq %rax, -0x300(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5900
movq -0x308(%rbp), %rdi
movq -0x300(%rbp), %rdx
movq %rax, %rcx
leaq 0x6a6c(%rip), %rsi      # 0xc7c1
movb $0x0, %al
callq 0x33c0
movq $0x0, -0x30(%rbp)
movq -0x8(%rbp), %rdi
leaq 0x6834(%rip), %rsi      # 0xc5a3
callq 0x5480
testb $0x1, %al
jne 0x5d7a
jmp 0x5d8a
movq 0xc227(%rip), %rax      # 0x11fa8
movq (%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x5dff
movq -0x8(%rbp), %rdi
callq 0x30e0
movq %rax, %rdi
leaq 0x6808(%rip), %rsi      # 0xc5a5
callq 0x3310
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x318(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
movq %rdi, -0x310(%rbp)
callq 0x30f0
movq -0x318(%rbp), %rdi
movq -0x310(%rbp), %rsi
callq 0x3780
jmp 0x5dda
leaq -0x50(%rbp), %rdi
callq 0x3170
jmp 0x5dff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x3170
jmp 0x6339
movl -0x14(%rbp), %esi
leaq -0xb0(%rbp), %rdi
callq 0xb070
movb $0x41, -0xdc(%rbp)
movb $0x43, -0xdb(%rbp)
movb $0x47, -0xda(%rbp)
movb $0x54, -0xd9(%rbp)
leaq -0xdc(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq $0x4, -0xd0(%rbp)
leaq -0xdd(%rbp), %rdi
movq %rdi, -0x320(%rbp)
callq 0x3460
movq -0x320(%rbp), %rcx
movq -0xd8(%rbp), %rsi
movq -0xd0(%rbp), %rdx
leaq -0xc8(%rbp), %rdi
callq 0xb0e0
jmp 0x5e79
leaq -0xdd(%rbp), %rdi
callq 0x32e0
movl $0x1, -0xe4(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5900
cmpq $0x0, %rax
jbe 0x6283
movq -0x10(%rbp), %rdi
callq 0xa450
movq %rax, -0xf8(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0xa510
movq (%rax), %rax
movq %rax, -0xf0(%rbp)
movq -0x10(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0xaf70
jmp 0x5eda
leaq -0x118(%rbp), %rdi
movq %rdi, -0x328(%rbp)
callq 0x33a0
movq -0x328(%rbp), %rdx
movq -0xf0(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0xb160
jmp 0x5f05
leaq -0x118(%rbp), %rdi
callq 0x30e0
movq %rax, %rsi
leaq -0xb0(%rbp), %rdi
callq 0xb1f0
jmp 0x5f22
movl $0x0, -0x124(%rbp)
cmpl $0x2, -0x124(%rbp)
jge 0x6182
cmpl $0x0, -0x124(%rbp)
jne 0x5f83
jmp 0x5f93
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xdd(%rbp), %rdi
callq 0x32e0
jmp 0x632d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x6321
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x6272
leaq -0x118(%rbp), %rdi
callq 0x3840
jmp 0x5f91
jmp 0x5f93
leaq -0x80(%rbp), %rax
movq %rax, -0x330(%rbp)
leaq -0x118(%rbp), %rdi
callq 0x30e0
movq -0x330(%rbp), %rdi
movq %rax, %rsi
movslq -0x14(%rbp), %rdx
callq 0x3110
movslq -0x14(%rbp), %rax
movb $0x0, -0x80(%rbp,%rax)
movb $0x1, -0x125(%rbp)
testb $0x1, -0x125(%rbp)
je 0x616c
movl $0x0, -0x12c(%rbp)
movl -0x12c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x601a
movl -0x12c(%rbp), %eax
addl $0x1, %eax
cltq
movb -0x80(%rbp,%rax), %cl
movslq -0x12c(%rbp), %rax
movb %cl, -0x80(%rbp,%rax)
movl -0x12c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x12c(%rbp)
jmp 0x5fe4
movslq -0x14(%rbp), %rax
movb $0x0, -0x80(%rbp,%rax)
movb $0x0, -0x125(%rbp)
leaq -0xc8(%rbp), %rax
movq %rax, -0x138(%rbp)
movq -0x138(%rbp), %rdi
callq 0xb2a0
movq %rax, -0x140(%rbp)
movq -0x138(%rbp), %rdi
callq 0xb2d0
movq %rax, -0x148(%rbp)
leaq -0x140(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0xb300
testb $0x1, %al
jne 0x607a
jmp 0x6167
leaq -0x140(%rbp), %rdi
callq 0xb340
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rax
movb (%rax), %cl
movl -0x14(%rbp), %eax
decl %eax
cltq
movb %cl, -0x80(%rbp,%rax)
movl -0x14(%rbp), %esi
leaq -0x80(%rbp), %rdi
leaq -0x120(%rbp), %rdx
callq 0x8520
jmp 0x60b6
movq -0x10(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0xb360
movq %rax, -0x338(%rbp)
jmp 0x60cf
movq -0x338(%rbp), %rax
cmpq $0x0, %rax
je 0x6154
cmpl $0x0, -0x124(%rbp)
jne 0x60ff
movq -0x150(%rbp), %rax
movsbl (%rax), %esi
leaq -0xb0(%rbp), %rdi
callq 0xb390
jmp 0x60fd
jmp 0x6119
movq -0x150(%rbp), %rax
movsbl (%rax), %esi
leaq -0xb0(%rbp), %rdi
callq 0xb410
jmp 0x6117
jmp 0x6119
movq -0x10(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0xaf70
jmp 0x612b
leaq -0xb0(%rbp), %rdi
callq 0xb490
movb %al, -0x339(%rbp)
jmp 0x613f
movb -0x339(%rbp), %al
testb $0x1, %al
jne 0x6152
jmp 0x614b
movb $0x1, -0x125(%rbp)
jmp 0x6167
jmp 0x6156
leaq -0x140(%rbp), %rdi
callq 0xb4d0
jmp 0x605e
jmp 0x5fcd
jmp 0x616e
movl -0x124(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x124(%rbp)
jmp 0x5f2c
leaq -0x2d8(%rbp), %rdi
callq 0x31c0
jmp 0x6190
leaq -0x2c8(%rbp), %rdi
leaq 0x66e1(%rip), %rsi      # 0xc87f
callq 0x3270
movq %rax, -0x348(%rbp)
jmp 0x61ac
movq -0x348(%rbp), %rdi
movl -0xe4(%rbp), %esi
callq 0x3440
jmp 0x61c0
leaq -0x2f8(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
callq 0x3260
jmp 0x61d5
movq -0x30(%rbp), %rax
movq %rax, -0x350(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x30e0
movq -0x350(%rbp), %rsi
movq %rax, %rdx
xorl %eax, %eax
movl %eax, %ecx
leaq -0xb0(%rbp), %rdi
callq 0xb4f0
jmp 0x6208
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x3170
leaq -0x2d8(%rbp), %rdi
callq 0x31e0
leaq -0x118(%rbp), %rdi
callq 0x3170
jmp 0x5e8f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x6266
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x3170
leaq -0x2d8(%rbp), %rdi
callq 0x31e0
leaq -0x118(%rbp), %rdi
callq 0x3170
jmp 0x6321
movq -0x30(%rbp), %rdi
callq 0x3280
jmp 0x628e
testb $0x1, -0x21(%rbp)
je 0x62fe
movq 0xbd55(%rip), %rdi      # 0x11ff0
leaq 0x65df(%rip), %rsi      # 0xc881
callq 0x3270
movq %rax, -0x358(%rbp)
jmp 0x62b0
movq -0x358(%rbp), %rdi
movl -0xe4(%rbp), %esi
callq 0x3440
movq %rax, -0x360(%rbp)
jmp 0x62cb
movq -0x360(%rbp), %rdi
leaq 0x65bf(%rip), %rsi      # 0xc898
callq 0x3270
movq %rax, -0x368(%rbp)
jmp 0x62e7
movq -0x368(%rbp), %rdi
movq 0xbcc3(%rip), %rsi      # 0x11fb8
callq 0x32b0
jmp 0x62fc
jmp 0x62fe
leaq -0xc8(%rbp), %rdi
callq 0xb5c0
leaq -0xb0(%rbp), %rdi
callq 0xb620
xorl %eax, %eax
addq $0x370, %rsp            # imm = 0x370
popq %rbp
retq
leaq -0xc8(%rbp), %rdi
callq 0xb5c0
leaq -0xb0(%rbp), %rdi
callq 0xb620
movq -0x58(%rbp), %rdi
callq 0x3450
nopw %cs:(%rax,%rax)
nopl (%rax)