// File: /workspace/github_cpp_makefile_star2_O2/simonrharris[P]SKA/src/sk_fastq.cpp
// Function: fastqToKmers(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<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&, int const&, int const&, int const&, int const&, float const&, bool)
int fastqToKmers(const std::vector < std::string > & fastqs, const std::string & outfilename, const int & kmerlen, const int & userminquality, const int & userfilecutoff, const int & usercovcutoff, const float & userminmaf, const bool printAlleles)
{

	const std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();//start the clock
	
	std::unordered_map < std::string, std::array < int, 8 > > kmerMap;//create a map to store the kmers for each base
	int substringlength=(kmerlen*2)+1;
	int numseqs=0;
	int numbases=0;
	int numreadbases=0;

	std::string sequence;
	sequence.reserve(500);
	std::string quality;
	quality.reserve(500);
	std::string subsequence;
	subsequence.reserve(500);
	std::string kmer;
	kmer.reserve((kmerlen*2)+1);
	char base;
	bool isFirst=true;

	for (int s = 0; s < fastqs.size(); ++s){
		
		std::cout << "Reading " << fastqs[s] << std::endl;
		igzstream gzfileStream;
		gzfileStream.open(fastqs[s].c_str());//open the fastq file
		if (gzfileStream.fail()){
			std::cerr << std::endl << "Error: Failed to open " << fastqs[s] << std::endl << std::endl;
			return 1;
		}

		while (gzfileStream.peek()!=EOF){
			if (readNextFastqSequence(gzfileStream, fastqs[s], sequence, quality)){return 1;};//read the next fastq sequence

			numseqs++;
			numreadbases+=sequence.length();

			lowqualitytoN(sequence, quality, userminquality);
			
			std::stringstream sequencestream;
			sequencestream << sequence;//convert the sequence to stringstream
			
			while (std::getline(sequencestream, subsequence, 'N')){//for each subsequence separated by Ns
				
				if (subsequence.length()<substringlength){//if the subsequence is too small then continue
					continue;
				}
				
				int i=0;
				
				for (i=0; i<subsequence.length()-(substringlength-1); ++i){//for each base in the subsequence
					
					kmer=subsequence.substr(i,substringlength);//extract the kmer from the subsequence
					
					reverseComplementIfMin(kmer);//If the rev comp of the kmer is 'smaller' then rev comp the kmer

					if(extractMiddleBase(kmer, base)){return 1;}//extract the middle base from the kmer

					addKmerToBaseArrayMap(kmerMap, kmer, base, isFirst);//add the kmer and base to the map
					
				}
				numbases+=i;
			}
    	}
		gzfileStream.close();//close the file
		isFirst=false;

		std::cout << "Added " << numbases << " kmers from " << numseqs << " sequences" << std::endl;
		std::cout << kmerMap.size() << " unique kmers in map" << std::endl;

		applyFileKmerArrayMapFilters(kmerMap, userfilecutoff);//Filter file kmers to remove those below the maf and file cov cutoff thresholds
		
	}

	applyFinalKmerArrayMapFilters(kmerMap, usercovcutoff);//Filter the kmers to remove those below the maf and cov cutoff thresholds
	
	if(printAlleles){
		if(printKmerAlleleFrequencies(kmerMap, outfilename+"_alleles.tsv")){return 1;}//print the kmers to file
	}

	if(printKmerFile(kmerMap, outfilename+".skf", kmerlen, userminmaf)){return 1;}//print the kmers to file

	printDuration(start);//stop the clock
	
	return 0;
	
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x5a8, %rsp            # imm = 0x5A8
movq %r9, 0x50(%rsp)
movq %r8, 0x48(%rsp)
movq %rcx, 0x58(%rsp)
movq %rdx, %rbx
movq %rsi, 0x20(%rsp)
movq %rdi, 0x30(%rsp)
callq 0x5050
movq %rax, 0x40(%rsp)
leaq 0xf8(%rsp), %rax
movq %rax, -0x30(%rax)
movq $0x1, -0x28(%rax)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rax)
movl $0x3f800000, -0x10(%rax) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
movq %rbx, 0x28(%rsp)
movslq (%rbx), %rbx
leaq 0x98(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x88(%rsp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x55f0
leaq 0xb8(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0xa8(%rsp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x55f0
leaq 0x78(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x68(%rsp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x55f0
leaq 0x110(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
movq 0x28(%rsp), %rax
movslq (%rax), %rax
leaq 0x1(,%rax,2), %rsi
leaq 0x100(%rsp), %rdi
callq 0x55f0
leaq 0x1(,%rbx,2), %r12
addq %rbx, %rbx
movslq %ebx, %rax
movq %rax, 0x60(%rsp)
movb $0x1, %al
movl %eax, 0x1c(%rsp)
xorl %ecx, %ecx
leaq 0x68(%rsp), %r14
leaq 0x100(%rsp), %r13
pushq $0x1
popq %rax
movl %eax, 0x10(%rsp)
movl $0x0, 0x18(%rsp)
movl $0x0, 0x14(%rsp)
movq 0x30(%rsp), %rbx
movq 0x8(%rbx), %rax
subq (%rbx), %rax
sarq $0x5, %rax
movq %rcx, 0x38(%rsp)
cmpq %rcx, %rax
jbe 0x10b42
movq 0x2573e(%rip), %rdi     # 0x35fb8
leaq 0x149fa(%rip), %rsi     # 0x2527b
callq 0x53f0
movq 0x38(%rsp), %rbp
shlq $0x5, %rbp
movq (%rbx), %rsi
addq %rbp, %rsi
movq %rax, %rdi
callq 0x53a0
movq %rax, %rdi
callq 0x51c0
leaq 0x308(%rsp), %r15
movq %r15, %rdi
callq 0x6d0a
movq (%rbx), %rax
movq (%rax,%rbp), %rsi
movq %r15, %rdi
pushq $0x8
popq %rdx
callq 0x710e
movq 0x308(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x328(%rsp,%rax)
je 0x10a28
movq 0x25708(%rip), %rdi     # 0x35ff0
callq 0x51c0
movq %rax, %rdi
leaq 0x14b29(%rip), %rsi     # 0x25420
callq 0x53f0
addq (%rbx), %rbp
movq %rax, %rdi
movq %rbp, %rsi
callq 0x53a0
movq %rax, %rdi
callq 0x51c0
movq %rax, %rdi
callq 0x51c0
jmp 0x10a74
leaq 0x88(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
movq 0x58(%rsp), %rdx
pushq $0x21
popq %rcx
callq 0x65ca
leaq 0x180(%rsp), %rdi
callq 0x52b0
leaq 0x190(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x53a0
incl 0x18(%rsp)
leaq 0x180(%rsp), %rdi
movq %r14, %rsi
pushq $0x4e
popq %rdx
callq 0x56e0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x10a1b
movq 0x70(%rsp), %rax
cmpq %r12, %rax
jb 0x10962
xorl %ebx, %ebx
subq 0x60(%rsp), %rax
cmpq %rbx, %rax
jbe 0x10a0d
leaq 0x160(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
callq 0x5420
movq %r13, %rdi
movq %r15, %rsi
callq 0x54a0
movq %r15, %rdi
callq 0x5778
movq %r13, %rdi
callq 0x6578
movq %r13, %rdi
leaq 0xf(%rsp), %rsi
callq 0x7c51
testl %eax, %eax
jne 0x10a67
movsbl 0xf(%rsp), %edx
movzbl 0x1c(%rsp), %ecx
andl $0x1, %ecx
leaq 0xc8(%rsp), %rdi
movq %r13, %rsi
callq 0x8a0f
incq %rbx
movq 0x70(%rsp), %rax
jmp 0x10993
addl %ebx, 0x14(%rsp)
movq 0x30(%rsp), %rbx
jmp 0x10962
leaq 0x180(%rsp), %rdi
callq 0x5320
leaq 0x490(%rsp), %rdi
callq 0x5140
cmpl $-0x1, %eax
je 0x10a98
movq (%rbx), %rsi
addq %rbp, %rsi
leaq 0x308(%rsp), %rdi
leaq 0x88(%rsp), %rdx
leaq 0xa8(%rsp), %rcx
callq 0x698f
testl %eax, %eax
je 0x1091f
jmp 0x10a74
leaq 0x180(%rsp), %rdi
callq 0x5320
xorl %ebx, %ebx
leaq 0x308(%rsp), %rdi
callq 0x6dea
movq 0x38(%rsp), %rcx
incq %rcx
testb %bl, %bl
jne 0x10855
jmp 0x10c05
leaq 0x308(%rsp), %rdi
callq 0x6db4
movq 0x2550c(%rip), %rdi     # 0x35fb8
leaq 0x150f6(%rip), %rsi     # 0x25ba9
callq 0x53f0
movq %rax, %rdi
movl 0x14(%rsp), %esi
callq 0x56a0
movq %rax, %rdi
leaq 0x150e2(%rip), %rsi     # 0x25bb0
callq 0x53f0
movq %rax, %rdi
movl 0x18(%rsp), %esi
callq 0x56a0
movq %rax, %rdi
leaq 0x15105(%rip), %rsi     # 0x25bee
callq 0x53f0
movq %rax, %rdi
callq 0x51c0
movq 0xe0(%rsp), %rsi
movq 0x254b3(%rip), %rdi     # 0x35fb8
callq 0x5280
movq %rax, %rdi
leaq 0x150c5(%rip), %rsi     # 0x25bd9
callq 0x53f0
movq %rax, %rdi
callq 0x51c0
leaq 0xc8(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0x8ab6
movb $0x1, %bl
movl $0x0, 0x1c(%rsp)
jmp 0x10a76
leaq 0xc8(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x8b69
cmpb $0x0, 0x5e8(%rsp)
je 0x10b9f
leaq 0x15094(%rip), %rdx     # 0x25bf9
leaq 0x140(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xbe9e
leaq 0xc8(%rsp), %rdi
leaq 0x140(%rsp), %rsi
callq 0x7f7a
movl %eax, %ebx
leaq 0x140(%rsp), %rdi
callq 0x5778
testl %ebx, %ebx
jne 0x10c05
leaq 0x1717c(%rip), %rdx     # 0x27d22
leaq 0x120(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xbe9e
movq 0x28(%rsp), %rax
movl (%rax), %edx
movq 0x5e0(%rsp), %rax
movss (%rax), %xmm0
leaq 0xc8(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x7cf2
movl %eax, %ebx
leaq 0x120(%rsp), %rdi
callq 0x5778
testl %ebx, %ebx
jne 0x10c05
movl $0x0, 0x10(%rsp)
movq 0x40(%rsp), %rdi
callq 0x7657
leaq 0x100(%rsp), %rdi
callq 0x5778
leaq 0x68(%rsp), %rdi
callq 0x5778
leaq 0xa8(%rsp), %rdi
callq 0x5778
leaq 0x88(%rsp), %rdi
callq 0x5778
leaq 0xc8(%rsp), %rdi
callq 0x10696
movl 0x10(%rsp), %eax
addq $0x5a8, %rsp            # imm = 0x5A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x140(%rsp), %rdi
jmp 0x10c71
movq %rax, %rbx
leaq 0x120(%rsp), %rdi
callq 0x5778
jmp 0x10cbe
jmp 0x10c93
movq %rax, %rbx
jmp 0x10ccb
movq %rax, %rbx
jmp 0x10cd5
movq %rax, %rbx
jmp 0x10ce2
jmp 0x10c93
jmp 0x10c98
jmp 0x10ca1
jmp 0x10c93
jmp 0x10c98
movq %rax, %rbx
jmp 0x10cbe
movq %rax, %rbx
jmp 0x10cb1
jmp 0x10ca1
jmp 0x10ca1
movq %rax, %rbx
leaq 0x180(%rsp), %rdi
callq 0x5320
leaq 0x308(%rsp), %rdi
callq 0x6dea
leaq 0x100(%rsp), %rdi
callq 0x5778
leaq 0x68(%rsp), %rdi
callq 0x5778
leaq 0xa8(%rsp), %rdi
callq 0x5778
leaq 0x88(%rsp), %rdi
callq 0x5778
leaq 0xc8(%rsp), %rdi
callq 0x10696
movq %rbx, %rdi
callq 0x56c0