package exp.twostep;

import java.security.InvalidAlgorithmParameterException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Collectors;

public class PvGen {
	DataRepresent mrna, tf, cnv, met;
	ArrayList<String> tfList, geneList, metList;
	int mode;
	
	int npairs = 10000; // for unconditional
	int nbins = 100; // number of bins
	int nsub = 100;
	
	private double[][] mi;
	private MI mic;
	
	public PvGen(DataRepresent mrna, DataRepresent tf, DataRepresent cnv, DataRepresent met, ArrayList<String> tfList, ArrayList<String> geneList, int mode){
		this.mrna = mrna;
		this.tf = tf;
		this.cnv = cnv;
		this.met = met;
		this.mode = mode;
		this.tfList = tfList;
		this.geneList = geneList;
		
		this.metList = new ArrayList<String>(met.content.keySet().stream().collect(Collectors.toSet()));
		
		mic = new MI();
		mi = new double[npairs][4];
	}
	
	public double[][] step1() throws InvalidAlgorithmParameterException{
		System.out.println("Ramdom sampling " + npairs + " pairs of genes and computing MI ... ");
		Random random = new Random();
		
		for (int i = 0; i < npairs; i++){
			if (i*100/npairs % 10 == 0){
				System.out.println(i*100/npairs + "% completed");
			}
			int ids = random.nextInt(geneList.size());
			int idd = 0;
			double foo = 0d;
			if (mode == Worker.MET){
				idd = random.nextInt(tfList.size());
				double[] genedata = mrna.content.get(geneList.get(ids));
				double[] tfdata = mrna.content.get(tfList.get(idd));
				
				double[][] a = new double[1][];
				double[][] b = new double[1][];
				double[][] c0 = new double[1][1];
				int k = (int)Math.ceil(tfdata.length * 0.16);
				
				a[0] = genedata;
				b[0] = tfdata;
				Arrays.fill(c0[0], 0d); 
				
				foo = mic.partialMutualInformation(a, b, c0, k);
			}
			if (mode == Worker.TF){
				idd = random.nextInt(metList.size());
				
				idd = random.nextInt(tfList.size());
				double[] genedata = mrna.content.get(geneList.get(ids));
				double[] metdata = met.content.get(metList.get(idd));
				
				double[][] a = new double[1][];
				double[][] b = new double[1][];
				double[][] c0 = new double[1][1];
				int k = (int)Math.ceil(metdata.length * 0.16);
				
				a[0] = genedata;
				b[0] = metdata;
				Arrays.fill(c0[0], 0d); 
				
				foo = mic.partialMutualInformation(a, b, c0, k);
			}
			mi[i][0] = ids;
			mi[i][1] = idd;
			mi[i][2] = foo;
			mi[i][4] = i;
			

		}
		System.out.println("Sorting the unconditional MI ...");
		double[][] mi_original = mi.clone();
		Arrays.sort(mi, (x,y) -> {
			if (x[2] < y[2])
				return -1;
			else if (x[2] > y[2])
				return 1;
			else
				return 0;
		});
		//original order is stored at mi[3]
		
		int bin_size = npairs / nbins;
		double[][] null_dist = new double[bin_size * nsub][nbins];
		double[][] bin_stat = new double[nbins][3];
		
		//start core cmi calculation here
		
		
		return null;
	}

}
