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 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_FLOODLIGHT_PRPOVIDER =
            MockFloodlightProvider.class;
    public static final Class<? extends IFloodlightModule> DEFAULT_THREADPOOL =
            MockThreadPoolService.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_FLOODLIGHT_PRPOVIDER);
        DEFAULT_MODULE_LIST.add(DEFAULT_THREADPOOL);

    }

    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;
    }
}
