package svm.instances.precomputed;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import svm.Mode;
import svm.SVMStruct;
import base.Example;
import base.SparseVector;

public class PrecomputedFeaturesProblem
{
	public static void main(String[] args) throws IOException
	{
		//computeSubmission();
		splitValidation();
	}

	private static void computeSubmission() throws FileNotFoundException, IOException
	{
		ArrayList<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>> train = loadData();
		PrecomputedFeaturesInstance instance = new PrecomputedFeaturesInstance();
		double C=1000;//421.87;
		SVMStruct<PrecomputedFeaturesInput, PrecomputedFeaturesOutput> svmstruct;
		do
		{
			System.out.println("C: "+C);
			svmstruct = new SVMStruct<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>(instance, C, 0.0001, Mode.MARGIN_RESCALING);
			svmstruct.train(train);
			C*=0.75;
		}
		while(C>0.00000001);
		//while(svmstruct.w.countNonZero()>25 && svmstruct.slack>8);
		
		double trainE = svmstruct.empiricalError(train);
		System.out.println(trainE);

		System.out.println(new SparseVector(svmstruct.w, svmstruct.wMap));
		ArrayList<PrecomputedFeaturesInput> test = loadTestData();
		System.out.println("Test Examples: " + test.size());
		for (PrecomputedFeaturesInput x : test)
		{
			// System.out.println(x.get(0).size());
			PrecomputedFeaturesOutput y = svmstruct.predict(x);
			System.out.print(x.annotations.get(y.selected).get("TRIP_ID") + ",");
			String[] loc = x.annotations.get(y.selected).get("clusterLocation").substring(1, x.annotations.get(y.selected).get("clusterLocation").length() - 1).split(",");
			System.out.println(loc[1] + "," + loc[0]);

		}
	}

	private static void splitValidation() throws FileNotFoundException, IOException
	{
		ArrayList<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>> data = loadData();
		ArrayList<double[]> performances = new ArrayList<double[]>();
		//for (int i = 0; i < 10; i++)
		{
			//Collections.shuffle(data);
			List<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>> train = data.subList(0, data.size()*3 / 4);
			List<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>> test = data.subList(1 + data.size()*3/4, data.size());

			PrecomputedFeaturesInstance instance = new PrecomputedFeaturesInstance();

			for (double C : new double[] { 0.0000001,0.00001,0.001 , 0.01, 0.1, 1, 10, 100, 1000, 1000000 })
				for (Mode m : new Mode[] { Mode.MARGIN_RESCALING })// , Mode.SLACK_RESCALING })
				{
					System.out.println("C: " + C);
					SVMStruct<PrecomputedFeaturesInput, PrecomputedFeaturesOutput> svmstruct = new SVMStruct<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>(instance, C, 0.01, m);
					svmstruct.train(train);
					double trainE = svmstruct.empiricalError(train);
					System.out.println(trainE);
					System.out.println(new SparseVector(svmstruct.w, svmstruct.wMap));
					//System.out.println(svmstruct.wMap);
					double testE = svmstruct.testError(test);
					System.out.println(testE);
					performances.add(new double[] { testE, trainE });
				}
		}
		System.out.println(performances.toString());
		for (double[] p : performances)
			System.out.println(Arrays.toString(p));
	}

	private static ArrayList<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>> loadData() throws FileNotFoundException, IOException
	{
		BufferedReader input = new BufferedReader(new FileReader("/Users/lukas/Documents/Uni/TaxiChallange/features2.csv"));
		//input.readLine();
		String[] header = input.readLine().split(";");
		System.out.println(Arrays.toString(header));
		PrecomputedFeaturesInput x = new PrecomputedFeaturesInput();
		ArrayList<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>> training = new ArrayList<Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>>();
		for (String line = input.readLine(); line != null; line = input.readLine())
		{
			if (line.trim().equals(""))
			{

				if (x.size() > 0)
				{
					int maxi = 0;
					for (int i = 0; i < x.loss.size(); i++)
					{
						if (x.loss.get(i) < x.loss.get(maxi))
							maxi = i;
					}
					PrecomputedFeaturesOutput y = new PrecomputedFeaturesOutput(x, maxi);
					Example<PrecomputedFeaturesInput, PrecomputedFeaturesOutput> e = new Example<>(x, y);
					training.add(e);

					x = new PrecomputedFeaturesInput();
				}
			}
			else
			{
				String[] columns = line.trim().split(";");
				// System.out.println(Arrays.toString(columns));
				SparseVector features = new SparseVector();

				for (int i = 0; i < columns.length; i++)
				{
					if (header[i].equals("loss"))
						x.loss.add(Double.parseDouble(columns[i]));
					else
					{
						try
						{
							features.put(header[i], Double.parseDouble(columns[i]));
						}
						catch (NumberFormatException e)
						{
							// if(!header[i].equals("callType"))
							// System.err.println("Can't parse " + columns[i] + " for field " + header[i] + ".");
						}
					}
				}
				x.add(features);
			}
		}
		return training;
	}

	private static ArrayList<PrecomputedFeaturesInput> loadTestData() throws FileNotFoundException, IOException
	{
		BufferedReader input = new BufferedReader(new FileReader("/Users/lukas/Documents/Uni/TaxiChallange/featuresSubmit.csv"));
		String[] header = input.readLine().split(";");
		System.out.println(Arrays.toString(header));
		PrecomputedFeaturesInput x = new PrecomputedFeaturesInput();
		ArrayList<PrecomputedFeaturesInput> training = new ArrayList<>();
		for (String line = input.readLine(); line != null; line = input.readLine())
		{
			if (line.trim().equals(""))
			{

				if (x.size() > 0)
				{
					training.add(x);

					x = new PrecomputedFeaturesInput();
				}
			}
			else
			{
				String[] columns = line.trim().split(";");
				// System.out.println(Arrays.toString(columns));
				SparseVector features = new SparseVector();
				HashMap<String, String> annotations = new HashMap<>();
				for (int i = 0; i < columns.length; i++)
				{
					if (header[i].equals("loss"))
						x.loss.add(Double.parseDouble(columns[i]));
					else
					{
						try
						{
							features.put(header[i], Double.parseDouble(columns[i]));
						}
						catch (NumberFormatException e)
						{
							annotations.put(header[i], columns[i]);
							// if(!header[i].equals("callType"))
							// System.err.println("Can't parse " + columns[i] + " for field " + header[i] + ".");
						}
					}
				}
				x.add(features);
				x.annotations.add(annotations);
			}
		}
		return training;
	}
}
