package exp.twostep;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;

public class Loading {
	
	private String mrnaInput, metInput, tfInput, cnvInput;
	private int mode = -1;
	
	private DataRepresent mrna;
	private DataRepresent met;
	private DataRepresent tf;
	private DataRepresent cnv;
	private ArrayList<Pair<String,String>> geneMet;
	private List<String> tfList;
	private int cores;
	private String shuffleFile;
	private String[] extraArgument;
	private double[][] seq;
	private int datalength;
	private int shuffle_N;
	
	public Loading(String... args){
		for (String s : args)
			System.out.println(s);
		
		if (args.length < 5){
			System.err.println("Not enough arguments");
			System.exit(-1);
		}
		cores = Runtime.getRuntime().availableProcessors();
		if (args.length >= 6){
			try{
				cores = Integer.parseInt(args[5]);
			}catch (NumberFormatException e){
				System.err.println("The argument \"Number of Thread\" is not correct.  I will use the number of available processers.");
				cores =  Runtime.getRuntime().availableProcessors();
			}
			System.out.println("greater than 6 argument");
			if (args.length > 6){
				extraArgument = new String[args.length - 6];
				shuffleFile = args[6]; //the 7th
				seq = readSeq(shuffleFile);
				
				for (int i = 6; i < args.length; i++){
					extraArgument[i - 6] = args[i]; //the first is shufflFile
					
				}
			}
		}
		System.out.println("Ready to load file");
		mrnaInput = args[0];
		metInput = args[1];
		tfInput = args[2];
		cnvInput = args[3];
		shuffle_N = 1000;
		if (extraArgument != null && extraArgument.length > 1){ //[0] is shuffleFile
			try{
				shuffle_N = Integer.parseInt(extraArgument[2]);
			}catch (Exception e){
				System.err.println("The shuffle_N is not correct, using 1000(default) instead.");
				shuffle_N = 1000;
			}
		}
		
		
		mode = -1;
		switch (args[4]){
		case "met":
			mode = Worker.MET;
			break;
		case "tf":
			mode = Worker.TF;
			break;
		}
		for (int i = 0; i < args.length; i++){
			System.out.println(args[i]);
		}
		
		int bootstrap = 1;
		double sample_ratio = 1;
		
		System.out.println("Start reading");
		
		try{
			System.out.println("before mrna");
			mrna = new DataRepresent(mrnaInput, 1, 2, "\t");
			System.out.println("after mrna");
			met = new DataRepresent(metInput, 1, 2, "\t");
			tf = new DataRepresent(tfInput, 1, 1, "\t");
			cnv = new DataRepresent(cnvInput, 1, 1, "\t");
		}catch (Exception e){
			e.printStackTrace();
		}
		

		
		final Set<String> keySetmRNA = mrna.content.keySet();
		tfList = tf.content.keySet().stream().filter((x)->{
			if (keySetmRNA.contains(x))
				return true;
			return false;
		}).sorted().collect(Collectors.toList());
		
		datalength = mrna.content.get(tfList.get(0)).length;
		
		final Set<String> targetMet = met.reverseTextMapper.keySet();
		List<String> geneList = mrna.content.keySet().stream().filter((x)->{
			if (targetMet.contains(x))
				return true;
			return false;
		}).sorted().collect(Collectors.toList());
		
		geneMet = new ArrayList<Pair<String,String>>();
		for (String s : geneList){
			
			String metLine = "";
			
			if (met.reverseTextMapper.containsKey(s))
				metLine = met.reverseTextMapper.get(s);
			else 
				continue;
			
			String[] metS = metLine.split(DataRepresent.otherTextDelimiter);
			for (String ms : metS){
				geneMet.add(new Pair<String, String>(s, ms));
			}
		}
		
		//print size
		System.out.println("(loading)result matrix size : " + tfList.size() + ", " + geneMet.size());
	}
	
	private double[][] readSeq(String file) {
		System.out.println("readSeq(), file = " + file);
		File f = new File(file);
		ArrayList<double[]> oo = new ArrayList<double[]>();
		double[][] output;
		
		if (!f.exists())
			return null;
		else{
			try (FileInputStream fis = new FileInputStream(f);
					Scanner sc = new Scanner(fis)){
				System.out.println("Ready to load seq");
				while (sc.hasNextLine()){
					String line = sc.nextLine();
//					System.out.println(line);
					if (line.length() < 3)
						continue;
					String[] spl = line.split("\t");
					double[] p = new double[]{Double.parseDouble(spl[0]), Double.parseDouble(spl[1])};
					oo.add(p);
//					System.out.println("" + p[0] + ", " + p[1]);
				}
				System.out.println("finish loading seq");
			}catch (FileNotFoundException fnfe){
				fnfe.printStackTrace(System.err);
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
		output = new double[oo.size()][2];
		for (int i = 0; i < oo.size(); i++){
			System.arraycopy(oo.get(i), 0, output[i], 0, 2);
		}
		System.out.println("exiting readSeq()");
		return output;
	}

	public int getMode(){
		return mode;
	}
	
	public int getThread(){
		return cores;
	}
	
	public List<String> getTFList(){
		return tfList;
	}
	
	public ArrayList<Pair<String,String>> getGeneMetCombination(){
		return geneMet;
	}
	
	public DataRepresent getmRNAData(){
		return mrna;
	}
	
	public DataRepresent getMetData(){
		return met;
	}
	
	public DataRepresent getCNVData(){
		return cnv;
	}
	
	public DataRepresent getTFData(){
		return tf;
	}
	
	
	public String[] getExtraArgument(){
		return extraArgument;
	}
	
	public String getShuffleFile(){
		return shuffleFile;
	}
	
	public double[][] getLocation(){
		return seq;
	}
	
	public int getLength(){
		return datalength;
	}
	
	public int getShuffle_N(){
		return shuffle_N;
	}
	
	
	
}
