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
     * @throws FloodlightModuleException
     */
    protected void startupModules(Collection<IFloodlightModule> moduleSet)
		throws FloodlightModuleException {
        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);
            }
        }
    }
}
