package pl.shockah.shocky.cmds; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import org.pircbotx.Channel; import org.pircbotx.PircBotX; import org.pircbotx.User; import pl.shockah.StringTools; import pl.shockah.shocky.Data; import pl.shockah.shocky.Module; public abstract class Command implements Comparable<Command> { private static final Map<Command, Object> cmdSources = Collections.synchronizedMap(new HashMap<Command, Object>()); private static final Map<String, Command> cmds = Collections.synchronizedSortedMap(new TreeMap<String, Command>()); private static final List<String> aliases = Collections.synchronizedList(new ArrayList<String>()); public static enum EType { Channel, Action, Private, Notice, Console; } static { Command cmdCtrl = new CmdController(); addCommands(null,cmdCtrl,new CmdBlacklist(),new CmdRaw(),new CmdDie(),new CmdSave(),new CmdGet(),new CmdSet(),new CmdModule()); addCommands(null,new CmdHelp(),new CmdJoin(),new CmdPart(),new CmdClean(),new CmdWeb()); addCommand(null,"ctrl",cmdCtrl); } public static void addCommand(Object source, String name, Command command) { synchronized(cmds) { cmdSources.put(command, source); cmds.put(name,command); aliases.add(name); } } public static void addCommands(Object source, Command... commands) { synchronized(cmds) { for (int i = 0; i < commands.length; i++) { cmdSources.put(commands[i], source); cmds.put(commands[i].command(),commands[i]); } } } public static void addCommands(Object source, Map<String,Command> commands) { synchronized(cmds) { for (Entry<String, Command> command : commands.entrySet()) { cmdSources.put(command.getValue(), source); cmds.put(command.getKey(), command.getValue()); } } } public static void removeCommands(String... commands) { synchronized(cmds) { for (int i = 0; i < commands.length; i++) { Command cmd = cmds.remove(commands[i]); if (cmd != null) { cmdSources.remove(cmd); aliases.remove(commands[i]); } } } } public static void removeCommands(Command... commands) { synchronized(cmds) { for (int i = 0; i < commands.length; i++) { boolean more = true; while (more) more = cmds.values().remove(commands[i]); cmdSources.remove(commands[i]); } } } public static Command getCommand(PircBotX bot, User sender, Channel channel, Command.EType type, CommandCallback callback, String name) { if (name == null || name.isEmpty()) return null; Map<String,Command> matchMap = getCommands(name, channel); if (matchMap.size()==1) return matchMap.values().iterator().next(); else if (matchMap.size()>1) { Object[] keys = matchMap.keySet().toArray(); String s = String.format("Did you mean: %s or %s",StringTools.implode(keys, 0, keys.length-2, ", "), keys[keys.length-1]); callback.type = EType.Notice; callback.append(s); } return null; } public static Map<String,Command> getCommands() { TreeMap<String,Command> map = new TreeMap<String,Command>(); synchronized(cmds) { for (String s : cmds.keySet()) { if (!aliases.contains(s)) map.put(s,cmds.get(s)); } } return Collections.unmodifiableSortedMap(map); } public static Map<String,Command> getCommands(String cmdName, Channel channel) { TreeMap<String,Command> matchMap = new TreeMap<String,Command>(); synchronized(cmds) { for (Entry<String, Command> cmd : cmds.entrySet()) { if (channel != null && !cmd.getValue().isEnabled(channel.getName())) continue; if (cmd.getKey().equals(cmdName)) return Collections.singletonMap(cmd.getKey(), cmd.getValue()); if (cmd.getKey().startsWith(cmdName)) matchMap.put(cmd.getKey(), cmd.getValue()); } } return matchMap; } public static boolean matches(Command command, PircBotX bot, EType type, Channel channel, String cmd) { if (type == EType.Channel) { if (cmd.length()<=1) return false; if (!Data.forChannel(channel).getString("main-cmdchar").contains(cmd.substring(0, 1))) return false; cmd=cmd.substring(1); } return getCommands(cmd, channel).keySet().size()==1; } public final int compareTo(Command command) { return command().compareTo(command.command()); } public abstract String command(); public abstract String help(Parameters params); public void visible(Parameters params) {} public abstract void doCommand(Parameters params, CommandCallback callback); public String toString() { return command(); } public boolean isEnabled(String channel) { Object source = cmdSources.get(this); if (source != null && source instanceof Module) { Module module = (Module)source; return module.isEnabled(channel); } return true; } }