package org.rki.readclassifier;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class DistClassifier implements ReadClassifier {
	private KmerDistribution[] kmers1;
	private KmerDistribution[] kmers2;
	public String org1name = "";
	public String org2name = "";
	private int kmersize;
	
	public String getName() {
		return "DistClassifier";
	}
	
	public String getDescription() {
		return "Classifies reads based on distance between Kmer frequency distributions.";
	}
	
	public void readData(InputStream in) throws Exception {
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		String line = reader.readLine();
		String[] dat = line.split("\\s+");
		if(!dat[0].equals("gaussian_dists")) {
			throw new Exception("Error: Wrong data file type. Found " + dat[0] + ", expected gaussian_dists");
		}
		kmersize = Integer.parseInt(dat[1].split("=")[1]);
		kmers1 = new KmerDistribution[(int)Math.pow(4, kmersize)];
		kmers2 = new KmerDistribution[(int)Math.pow(4, kmersize)];
//		Classifier.logger.log(Level.INFO, "Found kmer size: " + kmersize);
		org1name = dat[2].split("=")[1].trim();
		int currDist = 0;
		while(reader.ready()) {
			dat = reader.readLine().split("\\s+");
			if(dat[0].equals("gaussian_dists")) {
				currDist += 1;
				org2name = dat[2].split("=")[1].trim();
				continue;
			}
			double mean = Double.parseDouble(dat[1]);
			double sd = Double.parseDouble(dat[2]);
			int val = Classifier.calculateVal(dat[0].toCharArray());
			if(currDist == 0)
				kmers1[val] = new KmerDistribution(mean, sd);
			else
				kmers2[val] = new KmerDistribution(mean, sd);
		}
		reader.close();
	}
	
	public void getScore(ReadPair reads) {
		getReadScore(reads.read1);
		if(reads.read2 != null)
			getReadScore(reads.read2);
	}
	
	private void getReadScore(Read read) {
		char[] bases = read.bases.toCharArray();
		read.score = 0;
		read.score1 = 0;
		read.score2 = 0;
		double len = bases.length;
		int[] kmervals = new int[kmers1.length]; 
		char[] kmer = new char[kmersize];
		for(int i=0; i<bases.length-kmersize; i++) {
			for(int j=0; j<kmersize; j++) {
				kmer[j] = bases[i+j];
			}
			kmervals[Classifier.calculateVal(kmer)] += 1;
		}
		for(int i=0; i<kmervals.length; i++) {
			double val = kmervals[i]/(double)(len-kmersize+1);
			double score1 = kmers1[i].valueAt(val);
			double score2 = kmers2[i].valueAt(val);
			if(score1 + score2 != 0) {
				double fact = 100.0/(score1+score2);
				read.score += fact*(score1-score2);				
			}
			read.score1 += score1;
			read.score2 += score2;
		}				
	}
}
