package de.tu_darmstadt.tk.SmartHomeNetworkSim.core.anomalydetectors;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;

import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
import weka.clusterers.SimpleKMeans;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.SelectedTag;

public class KMeansAnomalyDetector extends BaseAnomalyDetector {

	/**
	 * Clusterer
	 */
	private SimpleKMeans clusterer;
	
	protected int NUMBER_OF_CLUSTERS = 34;
	
	Timestamp timestamp = new Timestamp(1);
	
	public KMeansAnomalyDetector() {
		super();
		// Initialize Clusterer
		clusterer = new SimpleKMeans();
		//clusterer.setSeed(42);
		clusterer.setInitializationMethod(new SelectedTag(SimpleKMeans.FARTHEST_FIRST,SimpleKMeans.TAGS_SELECTION));
		clusterer.setDisplayStdDevs(true);

		try {
			clusterer.setNumClusters(NUMBER_OF_CLUSTERS);
		} catch (Exception e) {
			System.out.println("Error while building cluster");
			e.printStackTrace();
		}
	}
	/**
	 * Try to classify the given packets and detect anomalies
	 * @param packets packets to be classified
	 */
	@Override
	public boolean classifyInstance(Instance instance) throws Exception {
		
		int x = clusterer.clusterInstance(instance);
		
		Instance center = clusterer.getClusterCentroids().get(x);
		Instance stdev = clusterer.getClusterStandardDevs().get(x);
		
		double distCenterInstance = clusterer.getDistanceFunction().distance(center, instance);
		double distCenterStdev = clusterer.getDistanceFunction().distance(center, stdev);
		
		if(distCenterInstance > distCenterStdev) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * Train the model using the given instances
	 * @param instances training set, which should be learned
	 */
	@Override
	public void trainModel(Instances instances) {
		try {
			clusterer.buildClusterer(instances);
			
			//save Model after clustering
			//saveModel();
		} catch (Exception e) {
			System.out.println("Kmeans clustering failed");
			e.printStackTrace();
		}
		
	}
	

	@Override
	public void saveModel() throws Exception {
		weka.core.SerializationHelper.write("./data/models/kmeans", clusterer);
	}
}
