// File: 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
movq %rsp, %rbp
subq $0x6b0, %rsp            # imm = 0x6B0
movb 0x18(%rbp), %al
movq 0x10(%rbp), %r10
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
andb $0x1, %al
movb %al, -0x39(%rbp)
callq 0x6080
movq %rax, -0x48(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x28920
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movl %ecx, %eax
leal 0x1(%rax,%rax), %eax
movl %eax, -0x84(%rbp)
movl $0x0, -0x88(%rbp)
movl $0x0, -0x8c(%rbp)
movl $0x0, -0x90(%rbp)
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x5d0(%rbp)
callq 0x6730
movq -0x5d0(%rbp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x6810
jmp 0x28c97
leaq -0xe0(%rbp), %rdi
movq %rdi, -0x5d8(%rbp)
callq 0x6730
movq -0x5d8(%rbp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x6810
jmp 0x28cbd
leaq -0x100(%rbp), %rdi
movq %rdi, -0x5e0(%rbp)
callq 0x6730
movq -0x5e0(%rbp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x6810
jmp 0x28ce3
leaq -0x120(%rbp), %rdi
movq %rdi, -0x5e8(%rbp)
callq 0x6730
movq -0x5e8(%rbp), %rdi
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movl %ecx, %eax
leal 0x1(%rax,%rax), %eax
movslq %eax, %rsi
callq 0x6810
jmp 0x28d13
movb $0x1, -0x122(%rbp)
movl $0x0, -0x128(%rbp)
movslq -0x128(%rbp), %rax
movq %rax, -0x5f0(%rbp)
movq -0x10(%rbp), %rdi
callq 0xb670
movq %rax, %rcx
movq -0x5f0(%rbp), %rax
cmpq %rcx, %rax
jae 0x2936b
movq 0x50253(%rip), %rdi     # 0x78fa8
leaq 0x3052b(%rip), %rsi     # 0x59287
callq 0x6520
movq %rax, -0x5f8(%rbp)
jmp 0x28d6a
movq -0x10(%rbp), %rdi
movslq -0x128(%rbp), %rsi
callq 0xf2d0
movq -0x5f8(%rbp), %rdi
movq %rax, %rsi
callq 0x64d0
movq %rax, -0x600(%rbp)
jmp 0x28d92
movq -0x600(%rbp), %rdi
movq 0x501f0(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x28da7
leaq -0x3c8(%rbp), %rdi
callq 0x92d0
jmp 0x28db5
movq -0x10(%rbp), %rdi
movslq -0x128(%rbp), %rsi
callq 0xf2d0
movq %rax, %rdi
callq 0x6210
movq %rax, %rsi
leaq -0x3c8(%rbp), %rdi
movl $0x8, %edx
callq 0x93d0
jmp 0x28de3
movq -0x3c8(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x3c8(%rbp,%rax), %rdi
callq 0x6030
movb %al, -0x601(%rbp)
jmp 0x28e03
movb -0x601(%rbp), %al
testb $0x1, %al
jne 0x28e12
jmp 0x28f2c
movq 0x501d7(%rip), %rdi     # 0x78ff0
movq 0x50170(%rip), %rsi     # 0x78f90
callq 0x6570
movq %rax, -0x610(%rbp)
jmp 0x28e2e
movq -0x610(%rbp), %rdi
leaq 0x305f4(%rip), %rsi     # 0x59430
callq 0x6520
movq %rax, -0x618(%rbp)
jmp 0x28e4a
movq -0x10(%rbp), %rdi
movslq -0x128(%rbp), %rsi
callq 0xf2d0
movq -0x618(%rbp), %rdi
movq %rax, %rsi
callq 0x64d0
movq %rax, -0x620(%rbp)
jmp 0x28e72
movq -0x620(%rbp), %rdi
movq 0x50110(%rip), %rsi     # 0x78f90
callq 0x6570
movq %rax, -0x628(%rbp)
jmp 0x28e8e
movq -0x628(%rbp), %rdi
movq 0x500f4(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x28ea3
movl $0x1, -0x4(%rbp)
movl $0x1, -0x3cc(%rbp)
jmp 0x29328
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x29523
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x29517
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x2950b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x294ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x2935a
jmp 0x28f2e
leaq -0x240(%rbp), %rdi
callq 0x61c0
movl %eax, -0x62c(%rbp)
jmp 0x28f42
movl -0x62c(%rbp), %eax
cmpl $-0x1, %eax
je 0x29209
movq -0x10(%rbp), %rdi
movslq -0x128(%rbp), %rsi
callq 0xf2d0
movq %rax, %rsi
leaq -0x3c8(%rbp), %rdi
leaq -0xb0(%rbp), %rdx
leaq -0xe0(%rbp), %rcx
callq 0x88c0
movl %eax, -0x630(%rbp)
jmp 0x28f86
movl -0x630(%rbp), %eax
cmpl $0x0, %eax
je 0x28fa7
movl $0x1, -0x4(%rbp)
movl $0x1, -0x3cc(%rbp)
jmp 0x29328
movl -0x88(%rbp), %eax
incl %eax
movl %eax, -0x88(%rbp)
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x638(%rbp)
callq 0x67e0
movq -0x638(%rbp), %rdi
movq %rax, %rcx
movl -0x90(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x90(%rbp)
movq -0x28(%rbp), %rdx
leaq -0xe0(%rbp), %rsi
movl $0x21, %ecx
callq 0x7f60
jmp 0x28ff7
leaq -0x558(%rbp), %rdi
callq 0x63a0
jmp 0x29005
leaq -0x548(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x64d0
jmp 0x2901a
jmp 0x2901c
leaq -0x558(%rbp), %rdi
leaq -0x100(%rbp), %rsi
movl $0x4e, %edx
callq 0x6960
movq %rax, -0x640(%rbp)
jmp 0x2903d
movq -0x640(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x6670
movb %al, -0x641(%rbp)
jmp 0x2905b
movb -0x641(%rbp), %al
testb $0x1, %al
jne 0x2906a
jmp 0x291de
leaq -0x100(%rbp), %rdi
callq 0x67e0
movslq -0x84(%rbp), %rcx
cmpq %rcx, %rax
jae 0x290a7
jmp 0x2901c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x558(%rbp), %rdi
callq 0x6410
jmp 0x2935a
movl $0x0, -0x55c(%rbp)
movl $0x0, -0x55c(%rbp)
movslq -0x55c(%rbp), %rax
movq %rax, -0x650(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x67e0
movq %rax, %rcx
movq -0x650(%rbp), %rax
movl -0x84(%rbp), %edx
subl $0x1, %edx
movslq %edx, %rdx
subq %rdx, %rcx
cmpq %rcx, %rax
jae 0x291c7
movslq -0x55c(%rbp), %rdx
movslq -0x84(%rbp), %rcx
leaq -0x580(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x6550
jmp 0x2911a
leaq -0x120(%rbp), %rdi
movq %rdi, -0x658(%rbp)
leaq -0x580(%rbp), %rsi
movq %rsi, -0x660(%rbp)
callq 0x6640
movq -0x660(%rbp), %rdi
callq 0x6a08
movq -0x658(%rbp), %rdi
callq 0x7ec0
jmp 0x29155
leaq -0x120(%rbp), %rdi
leaq -0x121(%rbp), %rsi
callq 0xbe60
movl %eax, -0x664(%rbp)
jmp 0x29170
movl -0x664(%rbp), %eax
cmpl $0x0, %eax
je 0x2918e
movl $0x1, -0x4(%rbp)
movl $0x1, -0x3cc(%rbp)
jmp 0x291e8
movsbl -0x121(%rbp), %edx
movzbl -0x122(%rbp), %ecx
andl $0x1, %ecx
leaq -0x80(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0xdd20
jmp 0x291b1
jmp 0x291b3
movl -0x55c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x55c(%rbp)
jmp 0x290bb
movl -0x55c(%rbp), %eax
addl -0x8c(%rbp), %eax
movl %eax, -0x8c(%rbp)
jmp 0x2901c
movl $0x0, -0x3cc(%rbp)
leaq -0x558(%rbp), %rdi
callq 0x6410
movl -0x3cc(%rbp), %eax
testl %eax, %eax
jne 0x29328
jmp 0x29204
jmp 0x28f2e
leaq -0x3c8(%rbp), %rdi
callq 0x9400
jmp 0x29217
movb $0x0, -0x122(%rbp)
movq 0x4fd83(%rip), %rdi     # 0x78fa8
leaq 0x3096d(%rip), %rsi     # 0x59b99
callq 0x6520
movq %rax, -0x670(%rbp)
jmp 0x2923a
movq -0x670(%rbp), %rdi
movl -0x8c(%rbp), %esi
callq 0x68d0
movq %rax, -0x678(%rbp)
jmp 0x29255
movq -0x678(%rbp), %rdi
leaq 0x3093d(%rip), %rsi     # 0x59ba0
callq 0x6520
movq %rax, -0x680(%rbp)
jmp 0x29271
movq -0x680(%rbp), %rdi
movl -0x88(%rbp), %esi
callq 0x68d0
movq %rax, -0x688(%rbp)
jmp 0x2928c
movq -0x688(%rbp), %rdi
leaq 0x30944(%rip), %rsi     # 0x59bde
callq 0x6520
movq %rax, -0x690(%rbp)
jmp 0x292a8
movq -0x690(%rbp), %rdi
movq 0x4fcda(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x292bd
leaq -0x80(%rbp), %rdi
callq 0xfbb0
movq %rax, %rsi
movq 0x4fcd8(%rip), %rdi     # 0x78fa8
callq 0x6120
movq %rax, -0x698(%rbp)
jmp 0x292de
movq -0x698(%rbp), %rdi
leaq 0x308dd(%rip), %rsi     # 0x59bc9
callq 0x6520
movq %rax, -0x6a0(%rbp)
jmp 0x292fa
movq -0x6a0(%rbp), %rdi
movq 0x4fc88(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x2930f
movq -0x30(%rbp), %rsi
leaq -0x80(%rbp), %rdi
callq 0xdeb0
jmp 0x2931e
movl $0x0, -0x3cc(%rbp)
leaq -0x3c8(%rbp), %rdi
callq 0x9480
movl -0x3cc(%rbp), %eax
testl %eax, %eax
jne 0x294ba
jmp 0x29344
jmp 0x29346
movl -0x128(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x128(%rbp)
jmp 0x28d24
leaq -0x3c8(%rbp), %rdi
callq 0x9480
jmp 0x294ff
movq -0x38(%rbp), %rsi
leaq -0x80(%rbp), %rdi
callq 0xe0a0
jmp 0x2937a
testb $0x1, -0x39(%rbp)
je 0x29407
movq -0x18(%rbp), %rsi
leaq 0x3085a(%rip), %rdx     # 0x59be9
leaq -0x5a0(%rbp), %rdi
callq 0x1ace0
jmp 0x2939d
leaq -0x80(%rbp), %rdi
leaq -0x5a0(%rbp), %rsi
callq 0xc510
movl %eax, -0x6a4(%rbp)
jmp 0x293b5
leaq -0x5a0(%rbp), %rdi
callq 0x6a08
movl -0x6a4(%rbp), %eax
cmpl $0x0, %eax
je 0x29405
movl $0x1, -0x4(%rbp)
movl $0x1, -0x3cc(%rbp)
jmp 0x294ba
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x5a0(%rbp), %rdi
callq 0x6a08
jmp 0x294ff
jmp 0x29407
movq -0x18(%rbp), %rsi
leaq 0x32904(%rip), %rdx     # 0x5bd16
leaq -0x5c0(%rbp), %rdi
callq 0x1ace0
jmp 0x29420
movq -0x20(%rbp), %rax
movl (%rax), %edx
movq 0x10(%rbp), %rax
movss (%rax), %xmm0
leaq -0x80(%rbp), %rdi
leaq -0x5c0(%rbp), %rsi
callq 0xbf80
movl %eax, -0x6a8(%rbp)
jmp 0x29446
leaq -0x5c0(%rbp), %rdi
callq 0x6a08
movl -0x6a8(%rbp), %eax
cmpl $0x0, %eax
je 0x29490
movl $0x1, -0x4(%rbp)
movl $0x1, -0x3cc(%rbp)
jmp 0x294ba
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x5c0(%rbp), %rdi
callq 0x6a08
jmp 0x294ff
movq -0x48(%rbp), %rax
movq %rax, -0x5c8(%rbp)
movq -0x5c8(%rbp), %rdi
callq 0xa8f0
jmp 0x294a9
movl $0x0, -0x4(%rbp)
movl $0x1, -0x3cc(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x6a08
leaq -0x100(%rbp), %rdi
callq 0x6a08
leaq -0xe0(%rbp), %rdi
callq 0x6a08
leaq -0xb0(%rbp), %rdi
callq 0x6a08
leaq -0x80(%rbp), %rdi
callq 0x28940
movl -0x4(%rbp), %eax
addq $0x6b0, %rsp            # imm = 0x6B0
popq %rbp
retq
leaq -0x120(%rbp), %rdi
callq 0x6a08
leaq -0x100(%rbp), %rdi
callq 0x6a08
leaq -0xe0(%rbp), %rdi
callq 0x6a08
leaq -0xb0(%rbp), %rdi
callq 0x6a08
leaq -0x80(%rbp), %rdi
callq 0x28940
movq -0xb8(%rbp), %rdi
callq 0x6900
nopw %cs:(%rax,%rax)
nop