package net.floodlightcontroller.core.module;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
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 COMPILED_CONF_FILE = 
            "floodlightdefault.properties";
    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.info("Loading default modules");
            InputStream is = this.getClass().getClassLoader().
                                    getResourceAsStream(COMPILED_CONF_FILE);
            try {
                prop.load(is);
            } catch (IOException e) {
                logger.error("Could not load default modules", e);
                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);
                            }
                        }
                    }
                }
            }
        }
        
        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);
            }
        }
    }
}
