package org.rki.readclassifier;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Reader extends Thread {
	private InputStream in1;
	private InputStream in2;
	private int numReads;
	private String lastLine1 = "";
	private String lastLine2 = "";
	private BufferedReader r1;
	private BufferedReader r2;
	private boolean isFastq = true;
	private boolean firstRead1 = true;
	private boolean firstRead2 = true;
	private int numThreads;
	
        public BlockingQueue<ReadPair> reads;
	public Boolean fileDone = false;
        public boolean stop = false;
	
	public Reader(InputStream infile1, InputStream infile2, int numReads, int bufferSize, int numThreads) {
		super();
		this.in1 = infile1;
		this.in2 = infile2;
		this.numReads = numReads;
		this.numThreads = numThreads;
		reads = new LinkedBlockingQueue<ReadPair>(numReads);
		r1 = new BufferedReader(new InputStreamReader(in1), bufferSize);
		r2 = in2==null?null:new BufferedReader(new InputStreamReader(in2));
	}
	
        public void run() {
            while(!fileDone) {
                readMore();
            }
            try {
            	for(int i=0; i<numThreads; i++) {
                    reads.put(new ReadPair(null, null));
            	}
                } catch(Exception e) {
                	e.printStackTrace();
                }
        }
        
	public void readMore() {
		if(fileDone)
			return;
		try {		
			int readsRead = 0;
			while(r1.ready()) {
				Read read1;
				read1 = readRead(r1, 1);
				Read read2 = readRead(r2, 2);
				reads.put(new ReadPair(read1, read2));
				readsRead += 1;
				if(readsRead >= numReads) {
					return;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		fileDone = true;
	}
	
	private Read readRead(BufferedReader reader, int numRead) throws IOException {
		if(reader == null)
			return null;
		String name = "";
		StringBuilder bases = new StringBuilder();
		StringBuilder qualities = new StringBuilder();
		String line = "";
		int numLines = 0;
		if((firstRead1 && numRead == 1) || (firstRead2 && numRead == 2)) {
			line = reader.readLine();
			if(line.charAt(0) == '>') {
				isFastq = false;
				if(numRead == 1) {
					lastLine1 = line;
					firstRead1 = false;
				}
				else if(numRead == 2) {
					lastLine2 = line;
					firstRead2 = false;
				}
			}
			else if(line.charAt(0) == '@') {
				isFastq = true;
				name = line.trim();
			}
			else
				throw new IOException("Read file has to be in FASTA or FASTQ format.");
		}
		if(isFastq) {
			if((numRead == 1 && !firstRead1) || (numRead == 2 && !firstRead2))
				name = reader.readLine().trim();
			while(true) {
				line = reader.readLine();
				if(line.charAt(0) == '+')
					break;
				numLines += 1;
				bases.append(line.trim());
			}
			while(numLines > 0) {
				line = reader.readLine();
				numLines -= 1;
				qualities.append(line.trim());
			}
			return new Read(name, bases.toString(), qualities.toString());
		}
		else {
			if(numRead == 1)
				name = lastLine1.trim();
			else if(numRead == 2)
				name = lastLine2.trim();
			while(reader.ready()) {
				line = reader.readLine();
				if(line.charAt(0) == '>') {
					if(numRead == 1)
						lastLine1 = line;
					else if(numRead == 2)
						lastLine2 = line;
					return new Read(name, bases.toString(), null);
				}
				bases.append(line.trim());
			}
			return new Read(name, bases.toString(), null);
		}
	}
	
}
