package org.rki.readtrainer;

import java.util.concurrent.atomic.AtomicInteger;

import org.rki.readclassifier.Classifier;
import org.rki.readclassifier.Read;
import org.rki.readclassifier.ReadPair;
import org.rki.readclassifier.Reader;

public class TrainerThread extends Thread {
	private Reader reader;
	private int kmermask;
	private AtomicInteger[][] matrix;
	
	public TrainerThread(Reader reader, AtomicInteger[][] matrix) {
		super();
		this.reader = reader;
		this.matrix = matrix;
	}
	
	public void run() {
		kmermask = (int)Math.pow(4, Trainer.kmersize) - 1;
		try {
			while(true) {
				ReadPair pair = reader.reads.take();
				if(pair.read1 == null)
					break;
				pair.read1.bases = pair.read1.bases.toUpperCase();
				trainRead(pair.read1);
				if(pair.read2 != null) {
					pair.read2.bases = pair.read2.bases.toUpperCase();
					trainRead(pair.read2);
				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	private void trainRead(Read read) {
		char[] bases = read.bases.toCharArray();
		read.score = 0;
		read.score1 = 1;
		read.score2 = 1;
		double len = bases.length;
		char[] kmer = new char[Trainer.kmersize];
		int i=0;
		int kmerval = 0;
		while(i<len && i<Trainer.kmersize) {
			kmer[i] = bases[i];
			i++;
		}
		kmerval = Classifier.calculateVal(kmer);
		for(; i<len; i++) {
			int nextbase = getBaseVal(bases[i]);
			matrix[kmerval][nextbase].addAndGet(1);
			kmerval = kmerval << 2;
			kmerval |= nextbase;
			kmerval &= kmermask;
		}
	}

	private int getBaseVal(char base) {
		switch (base) {
		case 'A':
			return 0;
		case 'C':
			return 1;
		case 'G':
			return 2;
		case 'T':
			return 3;
		default:
			return 0;
		}		
	}
}
