package io.shockah.skylark.factoids;
import java.util.Date;
import java.util.Map;
import java.util.regex.Pattern;
import io.shockah.skylark.Bot;
import io.shockah.skylark.commands.CommandCall;
import io.shockah.skylark.commands.CommandCall.Medium;
import io.shockah.skylark.commands.CommandParseException;
import io.shockah.skylark.commands.CommandResult;
import io.shockah.skylark.commands.NamedCommand;
import io.shockah.skylark.db.DatabaseManager;
import io.shockah.skylark.event.GenericUserMessageEvent;
import io.shockah.skylark.factoids.RememberCommand.Input;
import io.shockah.skylark.factoids.db.Factoid;
import io.shockah.skylark.factoids.db.FactoidIdent;
import io.shockah.skylark.ident.IdentMethod;
public class RememberCommand extends NamedCommand<Input, Factoid> {
private static final Pattern FACTOID_NAME_PATTERN = Pattern.compile("\\w\\S*");
private final FactoidsPlugin plugin;
public RememberCommand(FactoidsPlugin plugin) {
super("remember", "r");
this.plugin = plugin;
}
@Override
public Input convertToInput(GenericUserMessageEvent e, Object input) throws CommandParseException {
if (input instanceof Input)
return (Input)input;
return super.convertToInput(e, input);
}
@Override
public Input parseInput(GenericUserMessageEvent e, String input) throws CommandParseException {
String[] split = input.split("\\s");
if (split.length < 2)
throw new CommandParseException("Not enough arguments.");
Factoid.Context context = null;
String typeName = null;
String name = null;
String raw = null;
boolean append = false;
for (int i = 0; i < split.length; i++) {
String arg = split[i];
if (name == null) {
if (context == null && arg.charAt(0) == '@') {
String contextName = arg.substring(1);
context = Factoid.Context.valueOf(contextName);
if (context == null)
throw new CommandParseException(String.format("Invalid factoid context: %s", contextName));
} else if (typeName == null && arg.charAt(0) == '#') {
typeName = arg.substring(1);
FactoidType type = plugin.getType(typeName);
if (type == null)
throw new CommandParseException(String.format("Invalid factoid type: %s", typeName));
} else {
name = arg;
}
} else {
int length = 0;
for (int j = 0; j < i; j++) {
length += split[j].length() + 1;
}
raw = input.substring(length);
break;
}
}
if (name == null || raw == null)
throw new CommandParseException("Not enough arguments.");
if (context == null)
context = plugin.getDefaultContext();
if (typeName == null)
typeName = SimpleFactoidType.TYPE;
if (name.charAt(0) == '+') {
name = name.substring(1);
append = true;
}
return new Input(context, name, typeName, raw, append);
}
@Override
public CommandResult<Factoid> call(CommandCall call, Input input) {
if (!FACTOID_NAME_PATTERN.matcher(input.name).find())
throw new IllegalArgumentException("Illegal name.");
DatabaseManager databaseManager = plugin.manager.app.databaseManager;
databaseManager.delete(Factoid.class, (builder, where) -> {
where
.equals(Factoid.NAME_COLUMN, input.name)
.equals(Factoid.ACTIVE_COLUMN, false)
.equals(Factoid.CONTEXT_COLUMN, input.context);
if (input.context == Factoid.Context.Channel)
where
.equals(Factoid.SERVER_COLUMN, call.event.<Bot>getBot().manager.name)
.equals(Factoid.CHANNEL_COLUMN, call.event.getChannel().getName());
else if (input.context == Factoid.Context.Server)
where.equals(Factoid.SERVER_COLUMN, call.event.<Bot>getBot().manager.name);
});
String raw = input.raw;
if (input.append) {
Factoid currentFactoid = plugin.findActiveFactoid(call.event, input.name, input.context);
if (currentFactoid == null)
return CommandResult.error("Factoid doesn't exist.");
raw = String.format("%s\n%s", currentFactoid.raw, input.raw);
currentFactoid.update(obj -> {
obj.active = false;
});
}
final String f_raw = raw;
Factoid factoid = databaseManager.create(Factoid.class, obj -> {
obj.server = call.event.<Bot>getBot().manager.name;
obj.channel = call.event.getChannel().getName();
obj.context = input.context;
obj.name = input.name;
obj.type = input.typeName;
obj.raw = f_raw;
obj.date = new Date();
});
Map<IdentMethod, String> idents = plugin.identPlugin.getIdentsForUser(call.event.getUser());
for (Map.Entry<IdentMethod, String> entry : idents.entrySet()) {
if (entry.getValue() != null)
FactoidIdent.createOf(databaseManager, factoid, entry.getKey(), entry.getValue());
}
if (call.outputMedium == null)
call.outputMedium = Medium.Notice;
return CommandResult.of(factoid, "Done.");
}
public static final class Input {
public final Factoid.Context context;
public final String name;
public final String typeName;
public final String raw;
public final boolean append;
public Input(Factoid.Context context, String name, String typeName, String raw) {
this(context, name, typeName, raw, true);
}
public Input(Factoid.Context context, String name, String typeName, String raw, boolean append) {
this.context = context;
this.name = name;
this.typeName = typeName;
this.raw = raw;
this.append = append;
}
}
}