package org.orienteer.core.loader;

import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import org.kevoree.kcl.api.FlexyClassLoader;
import org.orienteer.core.loader.util.JarUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.file.Path;
import java.util.Iterator;
import java.util.Set;

/**
 * @author Vitaliy Gonchar
 */
public abstract class OrienteerOutsideModules {
    private static final Set<Path> LOADED = Sets.newConcurrentHashSet();
    private static final Logger LOG = LoggerFactory.getLogger(OrienteerOutsideModules.class);

    @Inject @Named("outside-modules")
    private static Path modulesFolder;
    @Inject
    private static OrienteerOutsideModulesManager manager;

    public static synchronized void registerModules() {
        LOG.info("Start load Orienteer outside modules");
        Set<Path> jarsInFolder = readModulesInFolder(modulesFolder);
        showAlreadyLoaded();
        for (Path jarFile : Sets.difference(jarsInFolder, LOADED)) {
            manager.setModulePath(jarFile);
            Optional<String> className = getInitClass(jarFile);
            if (className.isPresent()) {
                FlexyClassLoader moduleLoader = executeInitClass(className.get());
                if (moduleLoader != null) {
                    LOG.info("Load module: " + className.get() + " file: " + jarFile);
                    OLoaderStorage.addModuleLoader(className.get(), moduleLoader);
                    LOADED.add(jarFile);
                }

            } else LOG.warn("Cannot found init class for " + jarFile);
        }
        OLoaderStorage.updateRootLoader();
        LOG.info("End load Orienteer outside modules");
    }

    public static synchronized void unregisterModule(String moduleName) {
        if (OLoaderStorage.getNamesOfLoadedModules().contains(moduleName)) {
            FlexyClassLoader classLoader = OLoaderStorage.getModuleLoader(moduleName);
            FlexyClassLoader loader = manager.unregisterModule(classLoader);
            if (loader != null) {
                LOG.info("Unregistering module success");
                OLoaderStorage.removeModuleLoader(moduleName);
            }
        } else LOG.warn(String.format("Module with name %s is not loaded", moduleName));
    }

    private static void showAlreadyLoaded() {
        Iterator<Path> iterator = LOADED.iterator();
        for (String module : OLoaderStorage.getNamesOfLoadedModules()) {
            String file = iterator.hasNext() ? iterator.next().toString() : "";
            LOG.info("Already loaded: " + module + " file: " + file);
        }
    }

    private static String getModuleName(String initClassName) {
        String[] split = initClassName.split("\\.");
        return split[split.length - 2];
    }
    private static Set<Path> readModulesInFolder(Path folder) {
        return JarUtils.readJarsInFolder(folder);
    }

    private static Optional<String> getInitClass(Path jar) {
        return JarUtils.searchOrienteerInitModule(jar);
    }

    private static FlexyClassLoader executeInitClass(String className) {
        FlexyClassLoader moduleLoader = null;
        try {
            moduleLoader = manager.registerModule(className);
        } catch (ClassNotFoundException e) {
            LOG.error("Cannot load class");
            if (LOG.isDebugEnabled()) e.printStackTrace();
        }
        return moduleLoader;
    }

}

@@ -141,16 +141,51 @@
 Inject;%0A
+import com.google.inject.Injector;%0A
 import c
@@ -213,16 +213,16 @@
 .Named;%0A
-
 import o
@@ -306,16 +306,109 @@
 rUtils;%0A
+import org.orienteer.core.service.OrienteerFilter;%0Aimport org.orienteer.core.service.Reload;%0A
 import o
@@ -532,16 +532,111 @@
 til.Set;
+%0Aimport java.util.concurrent.ScheduledThreadPoolExecutor;%0Aimport java.util.concurrent.TimeUnit;
 %0A%0A/**%0A *
@@ -1029,16 +1029,67 @@
 nager;%0A%0A
+    @Inject%0A    private static Injector injector;%0A%0A
     publ
@@ -1288,24 +1288,43 @@
 dyLoaded();%0A
+        int i = 0;%0A
         for 
@@ -1859,32 +1859,57 @@
 D.add(jarFile);%0A
+                    i++;%0A
                 
@@ -2031,24 +2031,24 @@
 otLoader();%0A
-
         LOG.
@@ -2087,24 +2087,366 @@
  modules%22);%0A
+        if (i %3E 0) %7B%0A            reload();%0A        %7D%0A    %7D%0A%0A    private static void reload() %7B%0A        OrienteerFilter orienteerFilter = injector.getInstance(OrienteerFilter.class);%0A        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);%0A        executor.schedule(new Reload(orienteerFilter), 0, TimeUnit.SECONDS);%0A
     %7D%0A%0A    p

Fix error with loading modules with start Orienteer