package net.floodlightcontroller.core.module;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import net.floodlightcontroller.core.test.MockFloodlightProvider;
import net.floodlightcontroller.core.test.MockThreadPoolService;
import net.floodlightcontroller.counter.NullCounterStore;
import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier;
import net.floodlightcontroller.devicemanager.test.MockDeviceManager;
import net.floodlightcontroller.perfmon.NullPktInProcessingTime;
import net.floodlightcontroller.topology.TopologyManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FloodlightTestModuleLoader extends FloodlightModuleLoader {
	protected final static Logger log = LoggerFactory.getLogger(FloodlightTestModuleLoader.class);
	
	// List of default modules to use unless specified otherwise
	//public static final Class<? extends IFloodlightModule> DEFAULT_STORAGE_SOURCE =
			//MemoryStorageSource.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_FLOODLIGHT_PRPOVIDER =
			MockFloodlightProvider.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_TOPOLOGY_PROVIDER =
			TopologyManager.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_DEVICE_SERVICE =
			MockDeviceManager.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_COUNTER_STORE =
			NullCounterStore.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_THREADPOOL =
			MockThreadPoolService.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_ENTITY_CLASSIFIER =
			DefaultEntityClassifier.class;
	public static final Class<? extends IFloodlightModule> DEFAULT_PERFMON =
			NullPktInProcessingTime.class;
	
	protected static final Collection<Class<? extends IFloodlightModule>> DEFAULT_MODULE_LIST;
	
	static {
		DEFAULT_MODULE_LIST = new ArrayList<Class<? extends IFloodlightModule>>();
		DEFAULT_MODULE_LIST.add(DEFAULT_DEVICE_SERVICE);
		DEFAULT_MODULE_LIST.add(DEFAULT_FLOODLIGHT_PRPOVIDER);
		//DEFAULT_MODULE_LIST.add(DEFAULT_STORAGE_SOURCE);
		DEFAULT_MODULE_LIST.add(DEFAULT_TOPOLOGY_PROVIDER);
		DEFAULT_MODULE_LIST.add(DEFAULT_COUNTER_STORE);
		DEFAULT_MODULE_LIST.add(DEFAULT_THREADPOOL);
		DEFAULT_MODULE_LIST.add(DEFAULT_ENTITY_CLASSIFIER);
		DEFAULT_MODULE_LIST.add(DEFAULT_PERFMON);
	}
	
	protected IFloodlightModuleContext fmc;
	
	/**
	 * Adds default modules to the list of modules to load. This is done
	 * in order to avoid the module loader throwing errors about duplicate
	 * modules and neither one is specified by the user.
	 * @param userModules The list of user specified modules to add to.
	 */
	protected void addDefaultModules(Collection<Class<? extends IFloodlightModule>> userModules) {
		Collection<Class<? extends IFloodlightModule>> defaultModules =
				new ArrayList<Class<? extends IFloodlightModule>>(DEFAULT_MODULE_LIST.size());
		defaultModules.addAll(DEFAULT_MODULE_LIST);
		
		Iterator<Class<? extends IFloodlightModule>> modIter = userModules.iterator();
		while (modIter.hasNext()) {
			Class<? extends IFloodlightModule> userMod = modIter.next();
			Iterator<Class<? extends IFloodlightModule>> dmIter = defaultModules.iterator();
			while (dmIter.hasNext()) {
				Class<? extends IFloodlightModule> dmMod = dmIter.next();
				Collection<Class<? extends IFloodlightService>> userModServs;
				Collection<Class<? extends IFloodlightService>> dmModServs;
				try {
					dmModServs = dmMod.newInstance().getModuleServices();
					userModServs = userMod.newInstance().getModuleServices();
				} catch (InstantiationException e) {
					log.error(e.getMessage());
					break;
				} catch (IllegalAccessException e) {
					log.error(e.getMessage());
					break;
				}
				
				// If either of these are null continue as they have no services
				if (dmModServs == null || userModServs == null) continue;
				
				// If the user supplied modules has a service
				// that is in the default module list we remove
				// the default module from the list.
				boolean shouldBreak = false;
				Iterator<Class<? extends IFloodlightService>> userModServsIter 
					= userModServs.iterator();
				while (userModServsIter.hasNext()) {
					Class<? extends IFloodlightService> userModServIntf = userModServsIter.next();
					Iterator<Class<? extends IFloodlightService>> dmModsServsIter 
						= dmModServs.iterator();
					while (dmModsServsIter.hasNext()) {
						Class<? extends IFloodlightService> dmModServIntf 
							= dmModsServsIter.next();
						
						if (dmModServIntf.getCanonicalName().equals(
								userModServIntf.getCanonicalName())) {
							logger.debug("Removing default module {} because it was " +
									"overriden by an explicitly specified module",
									dmModServIntf.getCanonicalName());
							dmIter.remove();
							shouldBreak = true;
							break;
						}
					}
					if (shouldBreak) break;
				}
				if (shouldBreak) break;
			}
		}
		
		// Append the remaining default modules to the user specified ones.
		// This avoids the module loader throwing duplicate module errors.
		userModules.addAll(defaultModules);
		log.debug("Using module set " + userModules.toString());
	}
	
	/**
	 * Sets up all modules and their dependencies.
	 * @param modules The list of modules that the user wants to load.
	 * @param mockedServices The list of services that will be mocked. Any
	 * module that provides this service will not be loaded.
	 */
	public void setupModules(Collection<Class<? extends IFloodlightModule>> modules,
			Collection<IFloodlightService> mockedServices) {
		addDefaultModules(modules);
		Collection<String> modulesAsString = new ArrayList<String>();
		for (Class<? extends IFloodlightModule> m : modules) {
			modulesAsString.add(m.getCanonicalName());
		}
		
		try {
			fmc = loadModulesFromList(modulesAsString, null, mockedServices);
		} catch (FloodlightModuleException e) {
			log.error(e.getMessage());
		}
	}
	
	/**
	 * Gets the inited/started instance of a module from the context.
	 * @param ifl The name if the module to get, i.e. "LearningSwitch.class".
	 * @return The inited/started instance of the module.
	 */
	public IFloodlightModule getModuleByName(Class<? extends IFloodlightModule> ifl) {
		Collection<IFloodlightModule> modules = fmc.getAllModules();
		for (IFloodlightModule m : modules) {
			if (ifl.getCanonicalName().equals(m.getClass().getCanonicalName())) {
				return m;
			}
		}
		return null;
	}
	
	/**
	 * Gets an inited/started instance of a service from the context.
	 * @param ifs The name of the service to get, i.e. "ITopologyService.class".
	 * @return The inited/started instance of the service from teh context.
	 */
	public IFloodlightService getModuleByService(Class<? extends IFloodlightService> ifs) {
		Collection<IFloodlightModule> modules = fmc.getAllModules();
		for (IFloodlightModule m : modules) {
			Collection<Class<? extends IFloodlightService>> mServs = m.getModuleServices();
			if (mServs == null) continue;
			for (Class<? extends IFloodlightService> mServClass : mServs) {
				if (mServClass.getCanonicalName().equals(ifs.getCanonicalName())) {
					assert(m instanceof IFloodlightService);
					return (IFloodlightService)m;
				}
			}
		}
		return null;
	}
}
