package net.floodlightcontroller.core.module;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Queue;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.Set;

import net.floodlightcontroller.core.annotations.LogMessageDoc;
import net.floodlightcontroller.core.annotations.LogMessageDocs;

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

/**
 * Finds all Floodlight modules in the class path and loads/starts them.
 * @author alexreimers
 *
 */
public class FloodlightModuleLoader {
    protected final static Logger logger = 
            LoggerFactory.getLogger(FloodlightModuleLoader.class);

    protected static Map<Class<? extends IFloodlightService>,
                  Collection<IFloodlightModule>> serviceMap;
    protected static Map<IFloodlightModule,
                  Collection<Class<? extends 
                                   IFloodlightService>>> moduleServiceMap;
    protected static Map<String, IFloodlightModule> moduleNameMap;
    protected static Object lock = new Object();
    
    protected FloodlightModuleContext floodlightModuleContext;

    public static final String FLOODLIGHT_MODULES_KEY =
            "floodlight.modules";
    
	public FloodlightModuleLoader() {
	    floodlightModuleContext = new FloodlightModuleContext();
	}
	
	/**
	 * Finds all IFloodlightModule(s) in the classpath. It creates 3 Maps.
	 * serviceMap -> Maps a service to a module
	 * moduleServiceMap -> Maps a module to all the services it provides
	 * moduleNameMap -> Maps the string name to the module
	 * @throws FloodlightModuleException If two modules are specified in the configuration
	 * that provide the same service.
	 */
	protected static void findAllModules(Collection<String> mList) throws FloodlightModuleException {
	    synchronized (lock) {
	        if (serviceMap != null) return;
	        serviceMap = 
	                new HashMap<Class<? extends IFloodlightService>,
	                            Collection<IFloodlightModule>>();
	        moduleServiceMap = 
	                new HashMap<IFloodlightModule,
	                            Collection<Class<? extends 
	                                       IFloodlightService>>>();
	        moduleNameMap = new HashMap<String, IFloodlightModule>();
	        
	        // Get all the current modules in the classpath
	        ClassLoader cl = Thread.currentThread().getContextClassLoader();
	        ServiceLoader<IFloodlightModule> moduleLoader
	            = ServiceLoader.load(IFloodlightModule.class, cl);
	        // Iterate for each module, iterate through and add it's services
	        Iterator<IFloodlightModule> moduleIter = moduleLoader.iterator();
	        while (moduleIter.hasNext()) {
	        	IFloodlightModule m = null;
	        	try {
	        		m = moduleIter.next();
	        	} catch (ServiceConfigurationError sce) {
	        		logger.debug("Could not find module: {}", sce.getMessage());
	        		//moduleIter.remove();
	        		continue;
	        	}
	        //}
	        //for (IFloodlightModule m : moduleLoader) {
	            if (logger.isDebugEnabled()) {
	                logger.debug("Found module " + m.getClass().getName());
	            }

	            // Set up moduleNameMap
	            moduleNameMap.put(m.getClass().getCanonicalName(), m);

	            // Set up serviceMap
	            Collection<Class<? extends IFloodlightService>> servs =
	                    m.getModuleServices();
	            if (servs != null) {
	                moduleServiceMap.put(m, servs);
	                for (Class<? extends IFloodlightService> s : servs) {
	                    Collection<IFloodlightModule> mods = 
	                            serviceMap.get(s);
	                    if (mods == null) {
	                        mods = new ArrayList<IFloodlightModule>();
	                        serviceMap.put(s, mods);
	                    }
	                    mods.add(m);
	                    // Make sure they haven't specified duplicate modules in the config
	                    int dupInConf = 0;
	                    for (IFloodlightModule cMod : mods) {
	                        if (mList.contains(cMod.getClass().getCanonicalName()))
	                            dupInConf += 1;
	                    }
	                    
	                    if (dupInConf > 1) {
	                        String duplicateMods = "";
                            for (IFloodlightModule mod : mods) {
                                duplicateMods += mod.getClass().getCanonicalName() + ", ";
                            }
	                        throw new FloodlightModuleException("ERROR! The configuraiton" +
	                                " file specifies more than one module that provides the service " +
	                                s.getCanonicalName() +". Please specify only ONE of the " +
	                                "following modules in the config file: " + duplicateMods);
	                    }
	                }
	            }
	        }
	    }
	}
	
	/**
	 * Loads the modules from a specified configuration file.
	 * @param fName The configuration file path
	 * @return An IFloodlightModuleContext with all the modules to be started
	 * @throws FloodlightModuleException
	 */
	@LogMessageDocs({
	    @LogMessageDoc(level="INFO",
	            message="Loading modules from file {file name}",
	            explanation="The controller is initializing its module " +
	                    "configuration from the specified properties file"),
	    @LogMessageDoc(level="INFO",
	            message="Loading default modules",
	            explanation="The controller is initializing its module " +
	                    "configuration to the default configuration"),
	    @LogMessageDoc(level="ERROR",
	            message="Could not load module configuration file",
	            explanation="The controller failed to read the " +
	            		"module configuration file",
	            recommendation="Verify that the module configuration is " +
	            		"present. " + LogMessageDoc.CHECK_CONTROLLER),
	    @LogMessageDoc(level="ERROR",
                message="Could not load default modules",
                explanation="The controller failed to read the default " +
                        "module configuration",
                recommendation=LogMessageDoc.CHECK_CONTROLLER)
	})
	public IFloodlightModuleContext loadModulesFromConfig(String fName) 
	        throws FloodlightModuleException {
	    Properties prop = new Properties();
	    
	    File f = new File(fName);
	    if (f.isFile()) {
            logger.info("Loading modules from file {}", fName);
            try {
                prop.load(new FileInputStream(fName));
            } catch (Exception e) {
                logger.error("Could not load module configuration file", e);
                System.exit(1);
            }
        } else {
            logger.error("No configuration file specified");
            System.exit(1);
        }
        
        String moduleList = prop.getProperty(FLOODLIGHT_MODULES_KEY)
                                .replaceAll("\\s", "");
        Collection<String> configMods = new ArrayList<String>();
        configMods.addAll(Arrays.asList(moduleList.split(",")));
        return loadModulesFromList(configMods, prop);
	}
	
	/**
	 * Loads modules (and their dependencies) specified in the list
	 * @param mList The array of fully qualified module names
	 * @param ignoreList The list of Floodlight services NOT to 
	 * load modules for. Used for unit testing.
	 * @return The ModuleContext containing all the loaded modules
	 * @throws FloodlightModuleException
	 */
	protected IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop, 
			Collection<IFloodlightService> ignoreList) throws FloodlightModuleException {
		logger.debug("Starting module loader");
		if (logger.isDebugEnabled() && ignoreList != null)
			logger.debug("Not loading module services " + ignoreList.toString());

        findAllModules(configMods);
        
        Collection<IFloodlightModule> moduleSet = new ArrayList<IFloodlightModule>();
        Map<Class<? extends IFloodlightService>, IFloodlightModule> moduleMap =
                new HashMap<Class<? extends IFloodlightService>,
                            IFloodlightModule>();

        Queue<String> moduleQ = new LinkedList<String>();
        // Add the explicitly configured modules to the q
        moduleQ.addAll(configMods);
        Set<String> modsVisited = new HashSet<String>();
        
        while (!moduleQ.isEmpty()) {
            String moduleName = moduleQ.remove();
            if (modsVisited.contains(moduleName))
                continue;
            modsVisited.add(moduleName);
            IFloodlightModule module = moduleNameMap.get(moduleName);
            if (module == null) {
                throw new FloodlightModuleException("Module " + 
                        moduleName + " not found");
            }
            // If the module provies a service that is in the
            // services ignorelist don't load it.
            if ((ignoreList != null) && (module.getModuleServices() != null)) {
            	for (IFloodlightService ifs : ignoreList) {
            		for (Class<?> intsIgnore : ifs.getClass().getInterfaces()) {
            			//System.out.println(intsIgnore.getName());
        				// Check that the interface extends IFloodlightService
        				//if (intsIgnore.isAssignableFrom(IFloodlightService.class)) {
            			//System.out.println(module.getClass().getName());
    					if (intsIgnore.isAssignableFrom(module.getClass())) {
    						// We now ignore loading this module.
    						logger.debug("Not loading module " + 
    									 module.getClass().getCanonicalName() +
    									 " because interface " +
    									 intsIgnore.getCanonicalName() +
    									 " is in the ignore list.");
    						
    						continue;
    					}
        				//}
            		}
            	}
            }
            
            // Add the module to be loaded
            addModule(moduleMap, moduleSet, module);
            // Add it's dep's to the queue
            Collection<Class<? extends IFloodlightService>> deps = 
                    module.getModuleDependencies();
            if (deps != null) {
                for (Class<? extends IFloodlightService> c : deps) {
                    IFloodlightModule m = moduleMap.get(c);
                    if (m == null) {
                        Collection<IFloodlightModule> mods = serviceMap.get(c);
                        // Make sure only one module is loaded
                        if ((mods == null) || (mods.size() == 0)) {
                            throw new FloodlightModuleException("ERROR! Could not " +
                                    "find an IFloodlightModule that provides service " +
                                    c.toString());
                        } else if (mods.size() == 1) {
                            IFloodlightModule mod = mods.iterator().next();
                            if (!modsVisited.contains(mod.getClass().getCanonicalName()))
                                moduleQ.add(mod.getClass().getCanonicalName());
                        } else {
                            boolean found = false;
                            for (IFloodlightModule moduleDep : mods) {
                                if (configMods.contains(moduleDep.getClass().getCanonicalName())) {
                                    // Module will be loaded, we can continue
                                    found = true;
                                    break;
                                }
                            }
                            if (!found) {
                                String duplicateMods = "";
                                for (IFloodlightModule mod : mods) {
                                    duplicateMods += mod.getClass().getCanonicalName() + ", ";
                                }
                                throw new FloodlightModuleException("ERROR! Found more " + 
                                    "than one (" + mods.size() + ") IFloodlightModules that provides " +
                                    "service " + c.toString() + 
                                    ". Please specify one of the following modules in the config: " + 
                                    duplicateMods);
                            }
                        }
                    }
                }
            }
        }

	//
	// Reorder the moduleSet to take into account the module dependencies:
	// If a module depends on the service provided by another module, the
	// latter should be included before the former.
	//
	Collection<IFloodlightModule> orderedModuleSet =
	    new ArrayList<IFloodlightModule>();
	while (! moduleSet.isEmpty()) {
	    //
	    // Evaluate each module in the unsorted collection: if all its
	    // dependencies are in the orderedModuleSet, then add it to the
	    // orderedModuleSet.
	    //
	    boolean moduleWasSorted = false;
	    for (IFloodlightModule module : moduleSet) {
		Collection<Class<? extends IFloodlightService>> deps =
		    module.getModuleDependencies();
		boolean allDepsFound = true;
		if (deps != null) {
		    for (Class<? extends IFloodlightService> c : deps) {
			IFloodlightModule m = moduleMap.get(c);
			// NOTE: Earlier we checked that the module exists
			assert(m != null);
			if (! orderedModuleSet.contains(m)) {
			    allDepsFound = false;
			    break;
			}
		    }
		}

		// Move the module to the sorted collection
		if (allDepsFound) {
		    orderedModuleSet.add(module);
		    moduleSet.remove(module);
		    moduleWasSorted = true;
		    break;
		}
	    }

	    //
	    // Test for cyclic depenency:
	    // If no module was sorted, but there are still unsorted modules
	    // then there is cyclic dependency.
	    //
	    if ((! moduleWasSorted) && (! moduleSet.isEmpty())) {
		String errorMsg = "";
		for (IFloodlightModule module : moduleSet) {
		    if (! errorMsg.isEmpty())
			errorMsg += ", ";
		    errorMsg += module.getClass().getName();
		}
		errorMsg = "ERROR! Cyclic service dependency/dependencies among the following modules: " + errorMsg;
		throw new FloodlightModuleException(errorMsg);
	    }
	}
	moduleSet = orderedModuleSet;

        floodlightModuleContext.setModuleSet(moduleSet);
        parseConfigParameters(prop);
        initModules(moduleSet);
        startupModules(moduleSet);
        
        return floodlightModuleContext;
	}
	
	/**
	 * Loads modules (and their dependencies) specified in the list.
	 * @param configMods The collection of fully qualified module names to load.
	 * @param prop The list of properties that are configuration options.
	 * @return The ModuleContext containing all the loaded modules.
	 * @throws FloodlightModuleException
	 */
	public IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop) 
            throws FloodlightModuleException {
		return loadModulesFromList(configMods, prop, null);
    }
	
	/**
	 * Add a module to the set of modules to load and register its services
	 * @param moduleMap the module map
	 * @param moduleSet the module set
	 * @param module the module to add
	 */
	protected void addModule(Map<Class<? extends IFloodlightService>, 
                                           IFloodlightModule> moduleMap,
                            Collection<IFloodlightModule> moduleSet,
                            IFloodlightModule module) {
        if (!moduleSet.contains(module)) {
            Collection<Class<? extends IFloodlightService>> servs =
                    moduleServiceMap.get(module);
            if (servs != null) {
                for (Class<? extends IFloodlightService> c : servs)
                    moduleMap.put(c, module);
            }
            moduleSet.add(module);
        }
	}

    /**
     * Allocate  service implementations and then init all the modules
     * @param moduleSet The set of modules to call their init function on
     * @throws FloodlightModuleException If a module can not properly be loaded
     */
    protected void initModules(Collection<IFloodlightModule> moduleSet) 
                                           throws FloodlightModuleException {
        for (IFloodlightModule module : moduleSet) {            
            // Get the module's service instance(s)
            Map<Class<? extends IFloodlightService>, 
                IFloodlightService> simpls = module.getServiceImpls();

            // add its services to the context
            if (simpls != null) {
                for (Entry<Class<? extends IFloodlightService>, 
                        IFloodlightService> s : simpls.entrySet()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Setting " + s.getValue() + 
                                     "  as provider for " + 
                                     s.getKey().getCanonicalName());
                    }
                    if (floodlightModuleContext.getServiceImpl(s.getKey()) == null) {
                        floodlightModuleContext.addService(s.getKey(),
                                                           s.getValue());
                    } else {
                        throw new FloodlightModuleException("Cannot set "
                                                            + s.getValue()
                                                            + " as the provider for "
                                                            + s.getKey().getCanonicalName()
                                                            + " because "
                                                            + floodlightModuleContext.getServiceImpl(s.getKey())
                                                            + " already provides it");
                    }
                }
            }
        }
        
        for (IFloodlightModule module : moduleSet) {
            // init the module
            if (logger.isDebugEnabled()) {
                logger.debug("Initializing " + 
                             module.getClass().getCanonicalName());
            }
            module.init(floodlightModuleContext);
        }
    }
    
    /**
     * Call each loaded module's startup method
     * @param moduleSet the module set to start up
     */
    protected void startupModules(Collection<IFloodlightModule> moduleSet) {
        for (IFloodlightModule m : moduleSet) {
            if (logger.isDebugEnabled()) {
                logger.debug("Starting " + m.getClass().getCanonicalName());
            }
            m.startUp(floodlightModuleContext);
        }
    }
    
    /**
     * Parses configuration parameters for each module
     * @param prop The properties file to use
     */
    @LogMessageDoc(level="WARN",
                   message="Module {module} not found or loaded. " +
                           "Not adding configuration option {key} = {value}",
                   explanation="Ignoring a configuration parameter for a " +
                   		"module that is not loaded.")
    protected void parseConfigParameters(Properties prop) {
    	if (prop == null) return;
    	
        Enumeration<?> e = prop.propertyNames();
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            // Ignore module list key
            if (key.equals(FLOODLIGHT_MODULES_KEY)) {
                continue;
            }
            
            String configValue = null;
            int lastPeriod = key.lastIndexOf(".");
            String moduleName = key.substring(0, lastPeriod);
            String configKey = key.substring(lastPeriod + 1);
            // Check to see if it's overridden on the command line
            String systemKey = System.getProperty(key);
            if (systemKey != null) {
                configValue = systemKey;
            } else {
                configValue = prop.getProperty(key);
            }
            
            IFloodlightModule mod = moduleNameMap.get(moduleName);
            if (mod == null) {
                logger.warn("Module {} not found or loaded. " +
                		    "Not adding configuration option {} = {}", 
                            new Object[]{moduleName, configKey, configValue});
            } else {
                floodlightModuleContext.addConfigParam(mod, configKey, configValue);
            }
        }
    }
}
