package org.mcphoton.impl.plugin;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.mcphoton.impl.plugin.DependancyResolver.Solution;
import org.mcphoton.plugin.ClassSharer;
import org.mcphoton.plugin.Plugin;
import org.mcphoton.plugin.PluginLoader;
import org.mcphoton.plugin.PluginLoadingException;
import org.mcphoton.plugin.PluginsManager;

public class PhotonPluginsManager implements PluginsManager {

	private final Map<String, Plugin> loadedPlugins = new ConcurrentHashMap<>();
	private final ClassSharer classSharer = new PhotonClassSharer();
	private volatile PluginLoader defaultPluginLoader;

	@Override
	public Plugin getPlugin(String name) {
		return loadedPlugins.get(name);
	}

	@Override
	public boolean isPluginLoaded(String name) {
		return loadedPlugins.containsKey(name);
	}

	@Override
	public <T extends Plugin> T loadPlugin(File file, PluginLoader<T> loader) throws PluginLoadingException {
		T plugin = loader.loadPlugin(file);
		plugin.onLoad();
		loadedPlugins.put(plugin.getName(), plugin);
		return plugin;
	}

	@Override
	public <T extends Plugin> List<T> loadPlugins(File[] files, PluginLoader<T> loader) {
		List<T> plugins = loader.loadPlugins(files);
		Map<String, T> namesMap = new HashMap<>();
		DependancyResolver dependancyResolver = new DependancyResolver();
		for (T p : plugins) {
			namesMap.put(p.getName(), p);
			dependancyResolver.add(p);
		}
		Solution solution = dependancyResolver.resolve();
		List<T> result = new ArrayList<>();
		for (String name : solution.resolvedOrder) {
			T plugin = namesMap.get(name);
			try {
				plugin.onLoad();
				result.add(plugin);
				loadedPlugins.put(name, plugin);
			} catch (Throwable t) {// do not crash!
				t.printStackTrace();
			}
		}
		return result;
	}

	@Override
	public void unloadPlugin(Plugin plugin) {
		try {
			plugin.onUnload();
		} finally {
			plugin.getLoader().unloadPlugin(plugin);
			loadedPlugins.remove(plugin.getName());
		}
	}

	@Override
	public void unloadPlugin(String name) {
		unloadPlugin(getPlugin(name));
	}

	@Override
	public ClassSharer getClassSharer() {
		return classSharer;
	}

	@Override
	public PluginLoader getDefaultPluginLoader() {
		return defaultPluginLoader;
	}

	@Override
	public void setDefaultPluginLoader(PluginLoader loader) {
		this.defaultPluginLoader = loader;
	}

}

@@ -99,24 +99,51 @@
 il.HashMap;%0A
+import java.util.Iterator;%0A
 import java.
@@ -279,24 +279,62 @@
 r.Solution;%0A
+import org.mcphoton.impl.server.Main;%0A
 import org.m
@@ -792,16 +792,135 @@
 oader;%0A%0A
+%09public PhotonPluginsManager(PluginLoader defaultPluginLoader) %7B%0A%09%09this.defaultPluginLoader = defaultPluginLoader;%0A%09%7D%0A%0A
 %09@Overri
@@ -2333,24 +2333,335 @@
 name));%0A%09%7D%0A%0A
+%09public void unloadAllPlugins() %7B%0A%09%09Iterator%3CPlugin%3E it = loadedPlugins.values().iterator();%0A%09%09while (it.hasNext()) %7B%0A%09%09%09Plugin next = it.next();%0A%09%09%09try %7B%0A%09%09%09%09unloadPlugin(next);%0A%09%09%09%7D catch (Exception e) %7B%0A%09%09%09%09Main.serverInstance.logger.error(%22Error while unloading plugin %7B%7D%22, e, next.getName());%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D%0A%0A
 %09@Override%0A%09

Add unlodAllPlugins method and a constructor