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

import java.util.LinkedList;

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.PrecisionLink;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ProbabilityDistributionHandler;
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.ConstantValueDistributionHandler;
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.protocols.Ping_protocol;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleMQTT;
import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleProtocol;

/**
 * Class which stores the different imported classes
 *
 * @author Andreas T. Meyer-Berg
 */
public class ImportConfiguration {
	

	/*
	 * standard classes of the model, and user imported classes 
	 */
	private LinkedList<Class<? extends Protocol>> standardProtocols = new LinkedList<Class<? extends Protocol>>();
	private LinkedList<Class<? extends Protocol>> importedProtocols = new LinkedList<Class<? extends Protocol>>();
	
	private LinkedList<Class<? extends Link>> standardLinks = new LinkedList<Class<? extends Link>>();
	private LinkedList<Class<? extends Link>> importedLinks = new LinkedList<Class<? extends Link>>();
	
	private LinkedList<Class<? extends Connection>> standardConnections = new LinkedList<Class<? extends Connection>>();
	private LinkedList<Class<? extends Connection>> importedConnections = new LinkedList<Class<? extends Connection>>();
	
	private LinkedList<Class<? extends SmartDevice>> standardSmartDevices = new LinkedList<Class<? extends SmartDevice>>();
	private LinkedList<Class<? extends SmartDevice>> importedSmartDevices = new LinkedList<Class<? extends SmartDevice>>();
	
	private LinkedList<Class<? extends ProbabilityDistributionHandler>> standardDistributions = new LinkedList<Class<? extends ProbabilityDistributionHandler>>();
	private LinkedList<Class<? extends ProbabilityDistributionHandler>> importedDistribution = new LinkedList<Class<? extends ProbabilityDistributionHandler>>();
	/**
	 * Initializes the configuration and adds the standard classes
	 */
	public ImportConfiguration() {
		//Add the default Classes
		standardProtocols.add(MQTT_protocol.class);
		standardProtocols.add(Ping_protocol.class);
		standardProtocols.add(SimpleProtocol.class);
		standardProtocols.add(SimpleMQTT.class);
		
		standardLinks.add(SimpleLink.class);
		standardLinks.add(PrecisionLink.class);
		
		standardSmartDevices.add(SmartDevice.class);
		standardSmartDevices.add(BoolCollectorDevice.class);
		standardSmartDevices.add(FloatCollectorDevice.class);
		standardSmartDevices.add(BoolSensorDevice.class);
		standardSmartDevices.add(FloatSensorDevice.class);
		
		standardConnections.add(ConnectionPerformance.class);
		standardConnections.add(ConnectionPrecision.class);
		
		standardDistributions.add(ConstantValueDistributionHandler.class);
		standardDistributions.add(NormalDistributionHandler.class);
	}
	
	
	/**
	 * Returns Protocol Classes of the Model
	 * @return available Protocol Classes
	 */
	public LinkedList<Class<? extends Protocol>> getProtocolClasses(){
		LinkedList<Class<? extends Protocol>> export = new LinkedList<Class<? extends Protocol>>();
		export.addAll(standardProtocols);
		export.addAll(importedProtocols);
		return export;
	}
	
	/**
	 * Adds newProtocol to the available protocol classes
	 * @param newProtocol new Protocol Class to be added
	 */
	public void addProtocolClass(Class<? extends Protocol> newProtocol){
		importedProtocols.add(newProtocol);
	}
	
	/**
	 * Removes Protocol from the available protocol classes
	 * @param remove protocol to be removed
	 */
	public void removeProtocolClass(Class<? extends Protocol> remove){
		importedProtocols.remove(remove);
	}
	
	/**
	 * Returns Link Classes of the Model
	 * @return available Link classes
	 */
	public LinkedList<Class<? extends Link>> getLinkClasses(){
		LinkedList<Class<? extends Link>> export = new LinkedList<Class<? extends Link>>();
		export.addAll(standardLinks);
		export.addAll(importedLinks);
		return export;
	}
	
	/**
	 * Adds newLink to the available Link classes
	 * @param newLink new Link class to be added
	 */
	public void addLinkClass(Class<? extends Link> newLink){
		importedLinks.add(newLink);
	}
	
	/**
	 * Removes Link from the available Link classes
	 * @param remove Link Class to be removed
	 */
	public void removeLinkClass(Class<? extends Link> remove){
		importedLinks.remove(remove);
	}
	
	/**
	 * Returns Connection Classes of the Model
	 * @return available Connections classes
	 */
	public LinkedList<Class<? extends Connection>> getConnectionClasses(){
		LinkedList<Class<? extends Connection>> export = new LinkedList<Class<? extends Connection>>();
		export.addAll(standardConnections);
		export.addAll(importedConnections);
		return export;
	}
	
	/**
	 * Adds Connection Class to the available Connection Classes
	 * @param newConnection new Connection to be added
	 */
	public void addConnectionClass(Class<? extends Connection> newConnection){
		importedConnections.add(newConnection);
	}
	
	/**
	 * Removes Connection Class from the available Connection Classes
	 * @param remove Connection Class to be removed
	 */
	public void removeConnectionClass(Class<? extends Connection> remove){
		importedConnections.remove(remove);
	}
	
	/**
	 * Returns SmartDevice Classes of the Model
	 * @return available SmartDevice Classes
	 */
	public LinkedList<Class<? extends SmartDevice>> getSmartDeviceClasses(){
		LinkedList<Class<? extends SmartDevice>> export = new LinkedList<Class<? extends SmartDevice>>();
		export.addAll(standardSmartDevices);
		export.addAll(importedSmartDevices);
		return export;
	}
	
	/**
	 * Adds newSmartDevice Class to the available SmartDevice Classes
	 * @param newSmartDevice new SmartDevice Class to be added
	 */
	public void addSmartDeviceClass(Class<? extends SmartDevice> newSmartDevice){
		importedSmartDevices.add(newSmartDevice);
	}
	
	/**
	 * Removes SmartDevice Class from the available SmartDevice Classes
	 * @param remove SmartDevice Class to be removed
	 */
	public void removeSmartDeviceClass(Class<? extends SmartDevice> remove){
		importedSmartDevices.remove(remove);
	}

	
	/**
	 * Returns DistributionHandler Classes of the Model
	 * @return available DistributionHandler Classes
	 */
	public LinkedList<Class<? extends ProbabilityDistributionHandler>> getDistributionHandlerClasses(){
		LinkedList<Class<? extends ProbabilityDistributionHandler>> export = new LinkedList<Class<? extends ProbabilityDistributionHandler>>();
		export.addAll(standardDistributions);
		export.addAll(importedDistribution);
		return export;
	}
	
	/**
	 * Adds new DistributionHandler Class to the available DistributionHandler classes
	 * @param newDistributionHandler new DistributionHandler Class to be added
	 */
	public void addDistributionHandlerClass(Class<? extends ProbabilityDistributionHandler> newDistributionHandler){
		importedDistribution.add(newDistributionHandler);
	}
	
	/**
	 * Removes DistributionHandler Class from the available DistributionHandler Classes
	 * @param remove DistributionHandler Class to be removed
	 */
	public void removeDistributionHandlerClass(Class<? extends ProbabilityDistributionHandler> remove){
		importedDistribution.remove(remove);
	}
}
