package de.tudarmstadt.ukp.experiments.ej.repeatwithcrowdsource.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.math.stat.correlation.PearsonsCorrelation;

import de.tudarmstadt.ukp.dkpro.core.api.resources.DkproContext;

public class CombineTestResultsRegression
{
    public String experimentName; // such as StemsExperiment
    public int iAACeil; // on a scale of 0-100, as marked in the instanceID
    public int iAAFloor; 
    public File repository;
    public List<File> experiments;
    
    public List<Double> predictions;
    public List<Double> golds;
    public Double pearsonCorrelationTotal;
    

    public void setExperimentName(String aName){
        experimentName = aName;
    }
    public void setIaa(int aIaaFloor, int aIaaCeil){
        iAACeil = aIaaCeil;
        iAAFloor = aIaaFloor;
    }
    // makes list of experiments we want
    public void initialize() throws IOException{
        
        predictions = new ArrayList<Double>();
        golds = new ArrayList<Double>();
        
        repository = new File(DkproContext.getContext().getWorkspace("de.tudarmstadt.ukp.dkpro.lab").getAbsolutePath() + "/repository/");
        experiments = new ArrayList<File>();
        File[] allexperiments = repository.listFiles();
        
        for(File file: allexperiments){
            if(file.getName().contains("WekaTestTask-" + experimentName)){
                experiments.add(file);
            }
        }
        if(allexperiments.length < 2){
            throw new IOException("Error: Only " + allexperiments.length + " WekaTestTask files found.  "
                    + "Please fix and try again.");
        }
    }
    public void goThroughFiles() throws IOException{

        for(File file: experiments){
            File aResultsFile = new File(file, "id2outcome.txt");
            tabulatePredsAndGolds(aResultsFile);
        }
    }
    private void tabulatePredsAndGolds(File aResultsFile) throws IOException{
        List<Double> predictionsLocal = new ArrayList<Double>();
        List<Double> goldsLocal = new ArrayList<Double>();
        
        for(String line: FileUtils.readLines(aResultsFile)){
            if(line.startsWith("#")){
                continue;
            }
            int aIaa = new Integer(line.split("_")[0]); //expecting 75_1929_VIEW1_1929_VIEW2=0;1 where 75 is the IAA
            if(aIaa < iAAFloor || aIaa > iAACeil){
//                System.out.println("Skipping an instance: not within IAA range.");
                continue;
            }
            String[] eqSplit = line.split("=");
            Integer eqSplitSize = line.split("=").length;
            Double prediction = new Double(eqSplit[eqSplitSize-1].split(";")[0]);
            Double gold = new Double(eqSplit[eqSplitSize-1].split(";")[1].replace("\n", ""));
            
            predictionsLocal.add(prediction);
            goldsLocal.add(gold);
            predictions.add(prediction);
            golds.add(gold);
        }
    }
    
    public static double calculatePearson(List<Double> predictionsList, List<Double> goldsList){
        double[] predictionsArray = new double[predictionsList.size()];
        double[] goldsArray = new double[goldsList.size()];
        for(int i=0;i<predictionsArray.length;i++){
            predictionsArray[i] = predictionsList.get(i).doubleValue();
        }
        for(int i=0;i<goldsArray.length;i++){
            goldsArray[i] = goldsList.get(i).doubleValue();
        }
        
        double pearsonCorellation = new PearsonsCorrelation().correlation(predictionsArray, goldsArray);
//        double pearsonCorellation = PearsonReport.calculatePearson(predictionsArray, goldsArray);
        
        return pearsonCorellation;
    }
    private void printResults(){
        System.out.println("~~~~~~~~~~~~~CTRR Results~~~~~~~~~~~~~~~");
        System.out.println("Pearson Correlation for " + experimentName + ": " + r4(pearsonCorrelationTotal));
        System.out.println("Calculated on " + predictions.size() + " instances.");
        System.out.println("IAAFloor=" + iAAFloor + "  IAACeil=" + iAACeil);
    }
    private void printResultsLite(){
//        System.out.println("Calculated on " + predictions.size() + " instances.");
        System.out.println(" & " + r4(pearsonCorrelationTotal));
        ExperimentUtils.printTodaysResults(" & " + r4(pearsonCorrelationTotal));
    }
    private static Double r2(Double value){
        Double roundedValue = (double)Math.round(value * 100) / 100;
        return roundedValue;
    }
    private static Double r4(Double value){
        Double roundedValue = (double)Math.round(value * 10000) / 10000;
        return roundedValue;
    }
    public static void printForWebsite(List<Double> golds, List<Double> predictions){
    	System.out.println("\n~~~~~~~~~~~~~~~~~~~CTRR~~~~~~~~~~~~~~~~~~~~");
    	System.out.println("~~~~~~~~~~~~~Golds for website~~~~~~~~~~~~~~~");
    	for(Double gold: golds){
    		System.out.println(r2(gold));
    	}
    	System.out.println("~~~~~~~~~~~~Preds for website~~~~~~~~~~~");
    	for(Double pred: predictions){
    		System.out.println(r2(pred));
    	}
    	System.out.println("~~~~~~~~~~~~End of website~~~~~~~~~~~~~");
    	System.out.println("~~~~~~~~~~~~~~~~~CTRR~~~~~~~~~~~~~~~~\n");
    	
    }
    public static void callFromGroovyStarter(String myExperimentName, int iAAFloor, int iAACeil) throws IOException{
        CombineTestResultsRegression combo = new CombineTestResultsRegression();
        combo.setExperimentName(myExperimentName);
        combo.setIaa(iAAFloor, iAACeil);
        combo.run();
    }
    
    public void run()throws IOException{
        initialize();
        goThroughFiles();
        pearsonCorrelationTotal = calculatePearson(predictions, golds);
//        printForWebsite(golds, predictions);
//        printResults();
        printResultsLite();
    }
    
    public static void main(String[] args) throws IOException{
        String myExperimentName = "BiasedLangRegressionExperiment";
        CombineTestResultsRegression combo = new CombineTestResultsRegression();
        combo.setExperimentName(myExperimentName);
        combo.setIaa(60,130);//floor then ceil
        combo.run();
    }

}
