package de.kilobyte22.app.kibibyte.command;
import com.google.common.eventbus.Subscribe;
import de.kilobyte22.app.kibibyte.Kibibyte;
import de.kilobyte22.app.kibibyte.exceptions.CommandException;
import de.kilobyte22.app.kibibyte.exceptions.UsageException;
import de.kilobyte22.app.kibibyte.misc.Args;
import de.kilobyte22.app.kibibyte.misc.Utils;
import de.kilobyte22.app.kibibyte.plugin.BotAccess;
import de.kilobyte22.lib.logging.Logger;
import org.pircbotx.Channel;
import org.pircbotx.User;
import org.pircbotx.hooks.events.MessageEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Stephan
* Date: 15.02.13
* Time: 15:09
*
* @author ${user}
* @copyright Copyright ${year} ${user}
*/
public class CommandManager {
Kibibyte bot;
LinkedList<CommandManager> childs = new LinkedList<CommandManager>();
HashMap<String, Method> commands = new HashMap<String, Method>();
private Logger logger = new Logger("COMMANDSYS");
private CommandManager parent;
private boolean isEnabled = true;
private BotAccess botAccess;
public CommandManager(Kibibyte bot) {
this.bot = bot;
bot.eventBus.register(this);
}
public CommandManager(Kibibyte bot, CommandManager parent) {
this.bot = bot;
this.parent = parent;
parent.childs.add(this);
}
public CommandManager(Kibibyte bot, CommandManager parent, BotAccess botAccess) {
this(bot, parent);
this.botAccess = botAccess;
}
public CommandManager(CommandManager parent) {
this(parent.bot, parent);
}
@Subscribe
public void onMessage(MessageEvent event) {
if (parent != null) return;
String msg = Utils.getMessageWithoutPrefix(bot, event.getChannel().getName(), event.getMessage());
if (msg != null) {
//ChannelOutput out = new ChannelOutput();
//Bot bot = this.bot.botLookup.get(event.getBot());
//out.setDetails(event.getChannel(), event.getUser(), bot);
executeLine(msg, event.getChannel(), event.getUser(), bot);
bot.nickservSystem.flushAccount(event.getUser().getNick());
}
}
private void executeLine(String msg, Channel channel, User sender, Kibibyte bot) {
// parsing comes later
parseAndRun(msg, channel, sender, bot);
}
private void parseAndRun(String msg, Channel channel, User sender, Kibibyte bot) {
String cmdname = msg.split(" ")[0];
Method cmd = getCommand(cmdname);
if (cmd != null) {
Class<?extends CommandHandler> handlerClass = (Class<? extends CommandHandler>) cmd.getDeclaringClass();
if (!bot.permissionSystem.hasParsedPermission(cmd.getAnnotation(Command.class).permission(),sender.getNick(), channel)) {
bot.sendNotice(sender, "You don't have permissions to execute this command");
return;
}
try {
//"(\"(.*[^\\\\]|)\"|[^ ]+)" msg.substring(cmdname.length() + 1)
String argstring;
try {
argstring = msg.substring(cmdname.length() + 1);
} catch (Exception ex) {
argstring = "";
}
Args args_ = Utils.parseArgs(argstring);
//logger.log(LogLevel.DEBUG, args_.toString());
CommandHandler handler = handlerClass.newInstance();
if (botAccess == null)
handler.setData(bot, channel, sender, args_, cmd.getAnnotation(Command.class).name());
else
handler.setData(botAccess, channel, sender, args_, cmd.getAnnotation(Command.class).name());
try {
cmd.invoke(handler);
} catch (InvocationTargetException ex) {
try {
throw ex.getCause();
} catch (UsageException ex_) {
Command annotation = cmd.getAnnotation(Command.class);
logger.log(annotation.toString());
logger.log(bot.toString());
bot.sendNotice(sender, "Usage: " + cmdname + " " + annotation.usage());
} catch (CommandException ex_) {
bot.sendNotice(sender, "Error: " + ex_.getMessage());
} catch (Throwable throwable) {
logger.log(throwable);
}
}
} catch (Exception ex) {
logger.log(ex);
}
}
bot.nickservSystem.flushAccount(sender.getNick());
}
public void unregisterHandler(Class<?extends CommandHandler> handler) {
for(Method m : handler.getMethods()) {
Command annotation = m.getAnnotation(Command.class);
if (annotation != null) {
if (commands.get(annotation.name()) == m)
commands.remove(annotation.name());
for (String s : annotation.aliases()) {
if(commands.get(s) == m)
commands.remove(s);
}
}
}
}
public void registerHandler(Class<?extends CommandHandler> handler) {
for(Method m : handler.getMethods()) {
Command annotation = m.getAnnotation(Command.class);
if (annotation != null) {
commands.put(annotation.name(), m);
for (String s : annotation.aliases()) {
commands.put(s, m);
}
}
}
}
public Method getCommand(String name) {
return getCommand(name, null);
}
private Method getCommand(String name, CommandManager sender) {
if (!isEnabled) return null;
Method m = commands.get(name);
if (m != null) return m;
for (CommandManager child : childs) {
if (child != sender) {
m = child.getCommand(name, this);
if (m != null) return m;
}
}
if (parent != null && sender != parent)
return parent.getCommand(name, this);
return null;
}
public List<Method> getCommands(CommandManager sender) {
List<Method> ret = new LinkedList<Method>();
if (!isEnabled) return ret;
for (String s : commands.keySet()) {
ret.add(commands.get(s));
}
if (parent != null && sender != parent)
for (Method m : parent.getCommands(this)) {
ret.add(m);
}
for (CommandManager child : childs) {
if (child.isEnabled && child != sender)
for (Method m : child.getCommands(this)) {
ret.add(m);
}
}
return ret;
}
public void unlink() {
parent.childs.remove(this);
this.childs = new LinkedList<CommandManager>();
}
public void setEnabled(boolean state) {
isEnabled = state;
}
public List<Method> getCommands() {
return getCommands(null);
}
}