package pw.yumc.BukkitInjectedTools;

import java.io.File;
import java.net.URLDecoder;

import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import pw.yumc.injected.event.SetOpEvent;

/**
 * 注入工具集
 *
 * @since 2016年3月31日 下午7:44:25
 * @author 喵♂呜
 */
public class InjectedKit {
    public static String prefix = "§6[§bYum §a注入工具§6]§r ";
    public static String NMS = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];

    public static void fixPS(final CommandSender sender, final String path, final Class<?> clazz) {
        sender.sendMessage(prefix + "§c生成 ProtucolSupport 修复类...");
        try {
            final ClassPool pool = ClassPool.getDefault();
            final File classFile = new File(URLDecoder.decode(clazz.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8"));
            pool.appendClassPath(classFile.getPath());
            final CtClass statusListener = pool.get(clazz.getName());
            final CtMethod setOpMethod = statusListener.getDeclaredMethod("a");
            statusListener
                    .addField(CtField.make(
                            "private static final net.minecraft.server."
                                    + NMS
                                    + ".IChatBaseComponent infoAlreadySent = new net.minecraft.server."
                                    + NMS
                                    + ".ChatComponentText(\"Status request has already been handled.\");",
                            statusListener));
            statusListener.addField(CtField.make("private boolean sentInfo = false;", statusListener));
            final String checkStatus = "" + "{ if (sentInfo) { nmanager.close(infoAlreadySent); } sentInfo = true; }";
            setOpMethod.insertBefore(checkStatus);
            try {
                statusListener.writeFile(path);
                sender.sendMessage(prefix + "§a生成成功 §b请复制 §e" + path + " §b下所有文件到插件内部!");
            } catch (final Exception e) {
                e.printStackTrace();
                sender.sendMessage(prefix + "§4生成失败 请查看后台报错!");
            }
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    public static void injectProtocolSupport(final CommandSender sender, final String path, final boolean newver) {
        if (newver) {
            fixPS(sender, path, protocolsupport.protocol.packet.handler.StatusListener.class);
        } else {
            fixPS(sender, path, protocolsupport.protocol.transformer.handlers.StatusListener.class);
        }
    }

    public static void injectSetOpMethod(final CommandSender sender, final String path) {
        sender.sendMessage(prefix + "§c生成 SetOp 拦截类...");
        try {
            final ClassPool pool = ClassPool.getDefault();
            final String craftOfflinePlayerClassName = Bukkit.getServer().getClass().getPackage().getName() + ".CraftOfflinePlayer";
            final File classFile = new File(URLDecoder.decode(SetOpEvent.class.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8"));
            pool.appendClassPath(classFile.getPath());
            final CtClass craftOfflinePlayer = pool.get(craftOfflinePlayerClassName);
            final CtClass setOpEvent = pool.get(SetOpEvent.class.getName());
            final CtMethod setOpMethod = craftOfflinePlayer.getDeclaredMethod("setOp");
            final String setop = ""
                    + "{"
                    + "    pw.yumc.injected.event.SetOpEvent event = new pw.yumc.injected.event.SetOpEvent($0,$1);"
                    + "    org.bukkit.Bukkit.getPluginManager().callEvent(event);"
                    + "    if(event.isCancelled()){"
                    + "      return;"
                    + "    }"
                    + "    if ($1 == isOp()) {"
                    + "      return;"
                    + "    }"
                    + "    if ($1) {"
                    + "      server.getHandle().addOp(profile);"
                    + "    } else {"
                    + "      server.getHandle().removeOp(profile);"
                    + "    }"
                    + "}";
            setOpMethod.setBody(setop);
            try {
                setOpEvent.writeFile(path);
                craftOfflinePlayer.writeFile(path);
                sender.sendMessage(prefix + "§a生成成功 §b请复制 §e" + path + " §b下所有文件到服务器Jar内!");
            } catch (final Exception e) {
                e.printStackTrace();
                sender.sendMessage(prefix + "§4生成失败 请查看后台报错!");
            }
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}
