package de.tu_darmstadt.tk.SmartHomeNetworkSim.view.menuBar;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;

import javax.swing.JMenu;
import javax.swing.JMenuItem;

import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.ExampleAnomalyController;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.ImportController;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.NetworkController;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.PacketCaptureController;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.SettingsController;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.SimulationController;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ConnectionPerformance;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ConnectionPrecision;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PacketCollector;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PacketSniffer;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Port;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PrecisionLink;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Protocol;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.BoolCollectorDevice;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.BoolSensorDevice;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.FloatCollectorDevice;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.FloatSensorDevice;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.distributionHandler.NormalDistributionHandler;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.protocols.MQTT_protocol;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.CountingMetric;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.Manipulation_RandomMove;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleProtocol;

public class MenuBarNetworkExamples extends JMenu{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Controller controller
	 */
	private Controller controller;
	
	/**
	 * Controller for editing the network
	 */
	private NetworkController networkController;
	
	/**
	 * Controller to insert anomalies
	 */
	private ExampleAnomalyController anomalyController;
	
	/**
	 * Controller for configuration of the program
	 */
	private SettingsController settingsController;
	
	/**
	 * SimulationController for running the simulation
	 */
	private SimulationController simulationController;

	/**
	 * Creates the JMenu for network examples in the MenuBar
	 * @param controller controller to create examples
	 */
	public MenuBarNetworkExamples(Controller controller) {
		super("Create example Network");
		
		this.controller = controller;
		this.networkController = controller.getNetworkController();
		this.anomalyController = networkController.getAnomalyController();
		this.settingsController = controller.getSettingsController();
		this.simulationController = controller.getSimulationController();
		
		/**
		 * MQTT example
		 */
		JMenuItem mnMQTT = new JMenuItem("MQTT Example");
		mnMQTT.addActionListener(a->initializeMQTTTest());
		this.add(mnMQTT);
		
		/**
		 * Small Network Test
		 */
		JMenuItem mnTest = new JMenuItem("Network Example");
		mnTest.addActionListener(a->initializeTest());
		this.add(mnTest);
		
		/**
		 * Performance Comparison Example
		 */
		JMenuItem mnPerformance = new JMenuItem("Performane Evaluation Preset");
		mnPerformance.addActionListener(a->initializePerformanceTest());
		this.add(mnPerformance);
		
		/**
		 * User Study Preset
		 */
		JMenuItem mnUserStudy = new JMenuItem("User Study Preset");
		mnUserStudy.addActionListener(a->initializeUserStudy());
		this.add(mnUserStudy);
		
		/**
		 * Packet Collection example
		 */
		JMenuItem mnPacketCollectionExmample = new JMenuItem("Packet Collection Example");
		mnPacketCollectionExmample.addActionListener(a->testPackageCollection());
		this.add(mnPacketCollectionExmample);
		
		/**
		 * Paper example
		 */
		JMenuItem mnPaperExample = new JMenuItem("Paper Example");
		mnPaperExample.addActionListener(a->createPaperExample(false));
		this.add(mnPaperExample);
		
		/**
		 * Paper example + run
		 */
		JMenuItem mnRunPaperExample = new JMenuItem("Run Paper Example");
		mnRunPaperExample.addActionListener(a->createPaperExample(true));
		this.add(mnRunPaperExample);
	}

	private void initializePerformanceTest(){
		SmartDevice tic = new SmartDevice("Tic");
		tic.setX(100);
		tic.setY(100);
		SmartDevice toc = new SmartDevice("Toc");
		toc.setX(100);
		toc.setY(250);
		networkController.addSmartDevice(tic);
		networkController.addSmartDevice(toc);
		
		Link l = new PrecisionLink("Channel");
		networkController.addLink(l);
		networkController.addLinkToDevice(l, tic);
		networkController.addLinkToDevice(l, toc);

		Port ticP = new Port(tic, (short)2, 200, (short)0, 0, (short)0);
		Port tocP = new Port(toc, (short)3, 200, (short)0, -100, (short)0);
		tic.addPort(ticP);
		toc.addPort(tocP);
		
		Connection con = new ConnectionPrecision(l, new SimpleProtocol());
		networkController.addConnection(con);
		networkController.addConnectionToLink(con, l);
		networkController.addDeviceToConnectionAndProtocol(ticP, con, 0);
		networkController.addDeviceToConnectionAndProtocol(tocP, con, 1);
		
		simulationController.setStepDuration(100000000);
		simulationController.setEndTime(1000000000);
		controller.notifyObservers();
	}
	
	/**
	 * Initializes a basic test Network, which contains a few SmartDevices, one Link and one Connection
	 */
	private void initializeUserStudy(){
		/**
		 * Preset one SmartDevice
		 */
		SmartDevice A = new SmartDevice("Homestation");
		A.setX(200);
		A.setY(200);
		networkController.addSmartDevice(A);
		/**
		 * Packagecollector, which is registered at the Device
		 */
		PacketCollector collector = new PacketCollector(new CountingMetric());
		simulationController.getPacketCaptureController().addPacketCollector(collector);
		simulationController.getPacketCaptureController().addDeviceToCollector(collector, A);
		simulationController.setPrintPackets(true);
		controller.notifyObservers();
	}
	
	/**
	 * Test package collectors
	 */
	private void testPackageCollection() {
		if(networkController.getSmartDevices().size()<3)
			return;
		simulationController.addAlgorithm(new Manipulation_RandomMove(), controller);
	    PacketCollector collector = new PacketCollector();
	    simulationController.getSimulationManager().getPacketCollectionManager().addPacketCollector(collector);
	    
	    System.out.println("Collector 0-500 - nothing collected:");
	    simulationController.getSimulationManager().simulateTimeIntervall(0, 500);
	    HashMap<Link, LinkedList<Packet>> map = collector.getPackets();
	    for(Entry<Link, LinkedList<Packet>> e:map.entrySet()){
	    	System.out.println("Link: "+e.getKey().getName());
	    	for(Packet p : e.getValue())
	    		System.out.println(p.getTextualRepresentation());
	    }
	    
	    System.out.println("");
	    System.out.println("");
	    Iterator<SmartDevice> it = networkController.getSmartDevices().iterator();
	    it.next();
	    
	    SmartDevice d = it.next();
	    collector.addDevice(d);
	    SmartDevice f = it.next();
	    collector.addDevice(f);
	    System.out.println("Collector 500-1000 - "+d.getName()+" & "+f.getName()+" collected:");
	    simulationController.getSimulationManager().simulateTimeIntervall(500, 500);
	    map = collector.getPackets();
	    for(Entry<Link, LinkedList<Packet>> e:map.entrySet()){
	    	System.out.println("Link: "+e.getKey().getName());
	    	for(Packet p : e.getValue())
	    		System.out.println(p.getTextualRepresentation());
	    }

	    System.out.println("");
	    System.out.println("");
	    
	    Link l = networkController.getLinks().iterator().next();
	    collector.addLink(l);
	    System.out.println("Collector 2000-3000 - "+l+" collected:");
	    simulationController.getSimulationManager().simulateTimeIntervall(1000, 500);
	    map = collector.getPackets();
	    for(Entry<Link, LinkedList<Packet>> e:map.entrySet()){
	    	System.out.println("Link: "+e.getKey().getName());
	    	for(Packet p : e.getValue())
	    		System.out.println(p.getTextualRepresentation());
	    }
	    simulationController.resetSimulation();
		controller.notifyObservers();
	}
	
	/**
	 * Initializes a basic test Network, which contains a few SmartDevices, one Link and one Connection
	 */
	private void initializeTest(){
		SmartDevice A = null, B = null, C = null;
		for(int i = 0; i<5; i++){
			A = new SmartDevice("SmartTV"+i);		
			A.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			A.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			B = new SmartDevice("SmartDoor"+i);
			B.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			B.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			C = new SmartDevice("SmartLight"+i);
			C.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			C.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
		
			networkController.addSmartDevice(A);
			networkController.addSmartDevice(B);
			networkController.addSmartDevice(C);
		}
		
		Link link = new SimpleLink("SimpleWifi");
		link.addDevice(A);
		link.addDevice(B);
		link.addDevice(C);
		A.addLink(link);
		B.addLink(link);
		C.addLink(link);
		
		Port a = new Port(A, (short) 1, 68);
		a.setLastTrigger(0);
		a.setStatus(Port.SENDING);
		A.addPort(a);
		Port b = new Port(B, (short) 2, 102);
		b.setStatus(Port.SENDING);
		B.addPort(b);
		
		Connection s = new ConnectionPerformance(link, new SimpleProtocol(a, b));
		s.setPacketLossProbability(0.01);//1% Packet loss probability
		a.setConnection(s);
		b.setConnection(s);
		s.addSmartDevice(a);
		s.addSmartDevice(b);

		link.addConnection(s);
		
		networkController.addLink(link);
		networkController.addConnection(s);
		controller.notifyObservers();
	}
	
	/**
	 * Initializes a basic test Network, which contains a few SmartDevices, one Link and one Connection
	 */
	private void initializeMQTTTest(){
		SimpleLink link = new SimpleLink("WIFI");
		link.setFixedDelay(5);
		
		SmartDevice broker = new SmartDevice("MQTT-Broker");
		broker.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
		broker.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
		networkController.addSmartDevice(broker);
		
		Port brokerPort = new Port(broker, (short) 0, 987);
		brokerPort.setLastTrigger(0);
		brokerPort.setStatus(Port.OPEN);		
		broker.addPort(brokerPort);
		
		link.addDevice(broker);
		broker.addLink(link);
		
		Protocol protocol = new MQTT_protocol(brokerPort);
		
		Connection con = new ConnectionPrecision(link, protocol);
		con.setPacketLossProbability(0.01);//1% Packet loss probability
		con.addSmartDevice(brokerPort);
		brokerPort.setConnection(con);
		con.setStatus(Connection.ACTIVE);
		networkController.addLink(link);
		link.addConnection(con);
		networkController.addConnection(con);
		
		SmartDevice A = null, A1 = null, A2 = null, B = null, C = null;
		Port aP,a1P,a2P,bP,cP;
		for(int i = 0; i<3; i++){
			FloatSensorDevice aS = new FloatSensorDevice("SmartThermostat"+i+"(Pub)");	
			aS.setFSinfoName("room"+i+"/temperature");
			A=aS;
			A.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			A.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			link.addDevice(A);
			A.addLink(link);
			
			aP = new Port(A,((short) (3*i+1)),100+(int)(Math.random()*900));
			aP.setLastTrigger(0);
			aP.setJitter((short) (Math.random()*50));
			aP.setStatus(Port.SENDING);
			aP.setConnection(con);
			protocol.addDeviceOfRole(aP, 2);
			con.addSmartDevice(aP);
			A.addPort(aP);
			
			networkController.addSmartDevice(A);
			
			
			FloatCollectorDevice aS1 = new FloatCollectorDevice("SmartAirCondition"+i+"(Sub)");	
			aS1.setFCinfoName("room"+i+"/temperature");
			A1=aS1;
			A1.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			A1.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			link.addDevice(A1);
			A1.addLink(link);
			
			a1P = new Port(A1,((short) (3*i+1)),100+(int)(Math.random()*900));
			a1P.setLastTrigger(0);
			a1P.setJitter((short) (Math.random()*50));
			a1P.setStatus(Port.SENDING);
			a1P.setConnection(con);
			protocol.addDeviceOfRole(a1P, 3);
			con.addSmartDevice(a1P);
			A1.addPort(a1P);
			
			networkController.addSmartDevice(A1);
			
			
			FloatCollectorDevice aS2 = new FloatCollectorDevice("SmartHeater"+i+"(Sub)");	
			aS2.setFCinfoName("room"+i+"/temperature");
			A2=aS2;
			A2.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			A2.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			link.addDevice(A2);
			A2.addLink(link);
			
			a2P = new Port(A2,((short) (3*i+1)),100+(int)(Math.random()*900));
			a2P.setLastTrigger(0);
			a2P.setJitter((short) (Math.random()*50));
			a2P.setStatus(Port.SENDING);
			a2P.setConnection(con);
			protocol.addDeviceOfRole(a2P, 3);
			con.addSmartDevice(a2P);
			A2.addPort(a2P);
			
			networkController.addSmartDevice(A2);
			
			
			
			
			B = new BoolSensorDevice("SmartDoor"+i+"(Pub)");
			((BoolSensorDevice)B).setBSinfoName("room"+i+"/DoorOpen");
			B.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			B.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			link.addDevice(B);
			B.addLink(link);
			
			bP = new Port(B,((short) (3*i+2)),10+(int)(Math.random()*190));
			bP.setLastTrigger(0);
			bP.setJitter((short) (Math.random()*50));
			bP.setStatus(Port.SENDING);
			bP.setConnection(con);
			protocol.addDeviceOfRole(bP, 2);
			con.addSmartDevice(bP);
			B.addPort(bP);
			
			networkController.addSmartDevice(B);
			
			C = new BoolCollectorDevice("SmartDoorStatusLight"+i+"(Sub)");
			((BoolCollectorDevice)C).setBCinfoName("room"+i+"/DoorOpen");
			C.setX((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			C.setY((int)(Math.random()*settingsController.getWidth()-2*settingsController.getDeviceVisualizationRadius())+settingsController.getDeviceVisualizationRadius());
			link.addDevice(C);
			C.addLink(link);
			
			cP = new Port(C,((short) (3*i+1)), 50+(int)(Math.random()*450));
			cP.setLastTrigger(0);
			cP.setJitter((short) (Math.random()*50));
			cP.setStatus(Port.SENDING);
			cP.setConnection(con);
			protocol.addDeviceOfRole(cP, 3);
			con.addSmartDevice(cP);
			C.addPort(cP);
			
			networkController.addSmartDevice(C);
			controller.notifyObservers();
		}
	}
	
	/**
	 * Creates the paper toy example, also simulates it, if run = true
	 * @param run
	 */
	@SuppressWarnings("unchecked")
	public void createPaperExample(boolean run){
		/**
		 * Reset network, etc.
		 */
		if(run) {
			controller.getSimulationController().resetSimulation();
			controller.getNetworkController().deleteNetworkModel();
		}
		/*
		 * Main networking devices 
		 */
		SmartDevice router = networkController.createSmartDevice("Wifi-Router", 500, 100, 50);
		SmartDevice zigBeeRouter = networkController.createSmartDevice("ZigBee-Router", 500, 300, 50);
		SmartDevice broker = networkController.createSmartDevice("Broker", 500, 500, 50);
		
		/*
		 * Links/Networks
		 */
		Link wifi = new PrecisionLink("Wifi");
		networkController.addLink(wifi);
		Link zigbee = new PrecisionLink("ZigBee");
		networkController.addLink(zigbee);
		
		/*
		 * Connect Devices to Links
		 */
		networkController.addLinkToDevice(wifi, router);
		networkController.addLinkToDevice(wifi, zigBeeRouter);
		networkController.addLinkToDevice(zigbee, zigBeeRouter);
		networkController.addLinkToDevice(zigbee, broker);
		
		/*
		 * Internet Access Connection 
		 */
		Connection inetAcces = new ConnectionPrecision();
		inetAcces.setName("Cloud  Access");
		networkController.addConnectionToLink(inetAcces, wifi);
		inetAcces.setProtocol(new SimpleProtocol());
		Port pRouter = new Port(router, (short)80, 500L);
		pRouter.setTriggerHandler(new NormalDistributionHandler(500, 100));
		networkController.addDeviceToConnectionAndProtocol(pRouter, inetAcces, 0);
		Port pZigBee = new Port(zigBeeRouter, (short)80, 1000L);
		pZigBee.setTriggerHandler(new NormalDistributionHandler(1000, 300));
		networkController.addDeviceToConnectionAndProtocol(pRouter, inetAcces, 0);
		networkController.addDeviceToConnectionAndProtocol(pZigBee, inetAcces, 1);
		networkController.addConnection(inetAcces);
		
		/*
		 * ZigbeeRouter -> Broker ? 
		 */
		Connection homeAutomationInternetAccess = new ConnectionPrecision();
		homeAutomationInternetAccess.setName("Home Automation Webinterface");
		networkController.addConnectionToLink(homeAutomationInternetAccess, zigbee);
		homeAutomationInternetAccess.setProtocol(new SimpleProtocol());
		Port pBrokerWebInterface = new Port(broker, (short)80);
		pBrokerWebInterface.setTriggerHandler(new NormalDistributionHandler(2000, 500));
		pBrokerWebInterface.setStatus(Port.SENDING);
		pBrokerWebInterface.setResponseTime((short)2);
		pBrokerWebInterface.setLastTrigger(-284L);
		networkController.addDeviceToConnectionAndProtocol(pBrokerWebInterface, homeAutomationInternetAccess, 0);
		networkController.addConnection(homeAutomationInternetAccess);
		Port pRouterWebInterface = new Port(zigBeeRouter, (short)80);
		pRouterWebInterface.setTriggerHandler(new NormalDistributionHandler(5000, 3000));
		pRouterWebInterface.setStatus(Port.SENDING);
		pRouterWebInterface.setResponseTime((short)2);
		pRouterWebInterface.setLastTrigger(-142L);
		networkController.addDeviceToConnectionAndProtocol(pRouterWebInterface, homeAutomationInternetAccess, 1);
		networkController.addConnection(homeAutomationInternetAccess);
		
		
		/*
		 * Create MQTT Connection
		 */
		Connection mqtt = new ConnectionPrecision();
		mqtt.setName("Automation (MQTT)");
		networkController.addConnectionToLink(mqtt, zigbee);
		mqtt.setProtocol(new MQTT_protocol());
		Port pBroker = new Port(broker, (short)1883);
		pBroker.setStatus(Port.OPEN);
		pBroker.setResponseTime((short)2);
		networkController.addDeviceToConnectionAndProtocol(pBroker, mqtt, 0);
		networkController.addConnection(mqtt);
		
		/*
		 * Add some MQTT Devices
		 */
		
		/**
		 * Kitchen Thermostat
		 */
		FloatSensorDevice floatSensor = new FloatSensorDevice("Kitchen Thermostat");
		floatSensor.setFSinfoName("home/kitchen/temperature");
		networkController.addLinkToDevice(zigbee, floatSensor);
		networkController.moveSmartDevice(floatSensor, 300, 500, 50);
		floatSensor.setFSmin(15.0f);
		floatSensor.setFSmax(32.0f);
		networkController.addSmartDevice(floatSensor);
		Port pFloatSensor = new Port(floatSensor, (short)1883, 15000);
		pFloatSensor.setTriggerHandler(new NormalDistributionHandler(15000, 500));
		pFloatSensor.setStatus(Port.SENDING);
		pFloatSensor.setLastTrigger(-357L);
		networkController.addDeviceToConnectionAndProtocol(pFloatSensor, mqtt,1);
		
		/*
		 * Add Fridge
		 */
		FloatSensorDevice kitchenFridge = new FloatSensorDevice("Smart Fridge");
		kitchenFridge.setFSinfoName("home/kitchen/fridgeTemp");
		networkController.addLinkToDevice(zigbee, kitchenFridge);
		networkController.moveSmartDevice(kitchenFridge, 100, 600, 50);
		kitchenFridge.setFSmin(-4.0f);
		kitchenFridge.setFSmax(12.0f);
		networkController.addSmartDevice(kitchenFridge);
		Port pKitchenFridge = new Port(kitchenFridge, (short)1883, 15000);
		pKitchenFridge.setStatus(Port.SENDING);
		pKitchenFridge.setTriggerHandler(new NormalDistributionHandler(15000, 500));
		pKitchenFridge.setLastTrigger(-1231L);
		networkController.addDeviceToConnectionAndProtocol(pKitchenFridge, mqtt,1);
		
		
		/*
		 * Add some kitchen lights
		 */
		BoolSensorDevice kitchenLight = new BoolSensorDevice("Kitchen Light");
		kitchenLight.setBSinfoName("home/kitchen/light");
		networkController.addLinkToDevice(zigbee, kitchenLight);
		networkController.moveSmartDevice(kitchenLight, 250, 400, 50);
		networkController.addSmartDevice(kitchenLight);
		Port pKitchenLight = new Port(kitchenLight, (short)1883, 15000);
		pKitchenLight.setTriggerHandler(new NormalDistributionHandler(15000, 500));
		pKitchenLight.setStatus(Port.SENDING);
		pKitchenLight.setLastTrigger(-1207L);
		networkController.addDeviceToConnectionAndProtocol(pKitchenLight, mqtt,1);
		
		//TODO Further devices & Connections
		
		/*
		 * Bedroom
		 */
		BoolSensorDevice sleepingRoomLight = new BoolSensorDevice("Bedroom Light");
		sleepingRoomLight.setBSinfoName("home/bedroom/light");
		networkController.addLinkToDevice(zigbee, sleepingRoomLight);
		networkController.moveSmartDevice(sleepingRoomLight, 750, 400, 50);
		networkController.addSmartDevice(sleepingRoomLight);
		Port pBedroomLight = new Port(sleepingRoomLight, (short)1883, 15000);
		pBedroomLight.setTriggerHandler(new NormalDistributionHandler(15000, 500));
		pBedroomLight.setStatus(Port.SENDING);
		pBedroomLight.setLastTrigger(-1337L);
		networkController.addDeviceToConnectionAndProtocol(pBedroomLight, mqtt,1);
		
		/*
		 * Bedroom Thermostat
		 */
		FloatSensorDevice bedroomThermostat = new FloatSensorDevice("Bedroom Thermostat");
		bedroomThermostat.setFSinfoName("home/bedroom/temperature");
		networkController.addLinkToDevice(zigbee, bedroomThermostat);
		networkController.moveSmartDevice(bedroomThermostat, 700, 500, 50);
		bedroomThermostat.setFSmin(15.0f);
		bedroomThermostat.setFSmax(32.0f);
		networkController.addSmartDevice(bedroomThermostat);
		Port pBedroomThermostat = new Port(bedroomThermostat, (short)1883, 15000);
		pBedroomThermostat.setTriggerHandler(new NormalDistributionHandler(15000, 500));
		pBedroomThermostat.setStatus(Port.SENDING);
		pBedroomThermostat.setLastTrigger(-820L);
		networkController.addDeviceToConnectionAndProtocol(pBedroomThermostat, mqtt,1);
		
		
		/*
		 * Bedroom Info Screen
		 */
		FloatCollectorDevice bedroomInfoScreen = new FloatCollectorDevice("Information Panel");
		bedroomInfoScreen.setFCinfoName("home/kitchen/fridgeTemp");
		networkController.addLinkToDevice(zigbee, bedroomInfoScreen);
		networkController.moveSmartDevice(bedroomInfoScreen, 900, 600, 50);
		networkController.addSmartDevice(bedroomInfoScreen);
		Port pBedroomInfo = new Port(bedroomInfoScreen, (short)1883, 15000);
		pBedroomInfo.setStatus(Port.SENDING);
		pBedroomInfo.setTriggerHandler(new NormalDistributionHandler(15000, 500));
		pBedroomInfo.setLastTrigger(-666L);
		networkController.addDeviceToConnectionAndProtocol(pBedroomInfo, mqtt,1);
		/* 
		 * Update visualization 
		 */
		controller.notifyObservers();
		
		/**
		 * Run only if run == true
		 */
		if(!run)return;
		try {
			System.out.println("Check 1");//TODO
			/**
			 * Instances of the packet Sniffers
			 */
			PacketSniffer snifferEM = null, snifferKNN = null, snifferHC = null;
			/*
			 * Import Example PacketSniffer algorithms
			 */
			Class<? extends PacketSniffer> em = (Class<? extends PacketSniffer>) ImportController.importJavaClass(new File("examples/classifier/EMClustering.java"));
			snifferEM = em.newInstance();
			Class<? extends PacketSniffer> knn = (Class<? extends PacketSniffer>) ImportController.importJavaClass(new File("examples/classifier/KMeansClustering.java"));
			snifferKNN = knn.newInstance();
			Class<? extends PacketSniffer> hc = (Class<? extends PacketSniffer>) ImportController.importJavaClass(new File("examples/classifier/HierarchicalClustering.java"));
			snifferHC = hc.newInstance();

			System.out.println("Check 2: Imported");//TODO
			/*
			 * Create collectors
			 */
			PacketCollector collectorKNN = new PacketCollector(snifferKNN);
			//PacketCollector collectorEM = new PacketCollector(snifferEM);
			//PacketCollector collectorHC = new PacketCollector(snifferHC);
			
			/*
			 * Capture both links on all collectors
			 */
			PacketCaptureController captureController = controller.getSimulationController().getPacketCaptureController();
			//captureController.addLinkToCollector(collectorEM, zigbee);
			//captureController.addLinkToCollector(collectorEM, wifi);
			captureController.addLinkToCollector(collectorKNN, zigbee);
			captureController.addLinkToCollector(collectorKNN, wifi);
			//captureController.addLinkToCollector(collectorHC, zigbee);
			//captureController.addLinkToCollector(collectorHC, wifi);
			captureController.addPacketCollector(collectorKNN);
			//captureController.addPacketCollector(collectorEM);
			//captureController.addPacketCollector(collectorHC);

			System.out.println("Check 3: created Controller");//TODO
			
			/*
			 * Simulate 150000 ms (2 1/2 minutes)
			 */
			SimulationController sim = controller.getSimulationController();
			sim.setStartTime(0);
			sim.resetSimulation();
			sim.setStepDuration(15000);
			sim.setPrintPackets(false);
			sim.setEndTime(150000);

			for(int i=0; i<10; i++)
				sim.getSimulationManager().simulateTimeIntervall(15000*i, 15000);

			collectorKNN.setMode(true);
			//collectorEM.setMode(true);
			//collectorHC.setMode(true);
			
			System.out.println("Check 4: Trained");//TODO
			
			/*
			 * Simulate/Test 30000 without anomalies
			 */

			for(int i=10; i<12; i++)
				sim.getSimulationManager().simulateTimeIntervall(15000*i, 15000);
			System.out.println("Check 5: tested w/0 anomalies");//TODO
			
			/**
			 * Insert anomaly & Simulate further packets
			 */
			Connection ddos = anomalyController.openDDosCreationMenu(broker, new LinkedList<SmartDevice>(zigbee.getDevices()));
			Connection dos = anomalyController.runDosAttack(kitchenLight, kitchenFridge);
			/**
			 * Start Testing another 30000
			 */
			sim.setEndTime(210000);
			

			for(int i=12; i<14; i++)
				sim.getSimulationManager().simulateTimeIntervall(15000*i, 15000);
			

			System.out.println("Check 6: Tested w anomalies");//TODO
			
			System.out.println("Testing completed");
		} catch(Exception e) {
			System.out.println("WARNING: Testing failed: ");
			e.printStackTrace();
		}
	}
}
