package tc.oc.pgm.destroyable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import tc.oc.commons.core.commands.Commands;
import tc.oc.pgm.commands.CommandUtils;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.inject.MatchScoped;
import static tc.oc.commons.core.exception.LambdaExceptionUtils.rethrowSupplier;
@MatchScoped
public class DestroyableCommands implements Commands {
private final Optional<DestroyableMatchModule> module;
@Inject private DestroyableCommands(Optional<DestroyableMatchModule> module) {
this.module = module;
}
private DestroyableMatchModule matchModule() throws CommandException {
return module.orElseThrow(() -> new CommandException("No destroyables"));
}
private Destroyable lookup(Match match, String slug) throws CommandException {
return match.features()
.bySlug(Destroyable.class, slug)
.orElseGet(rethrowSupplier(() -> {
final List<Destroyable> destroyables = match.features()
.all(Destroyable.class)
.filter(d -> d.slug().startsWith(slug))
.collect(Collectors.toList());
switch(destroyables.size()) {
case 0: throw new CommandException("No destroyable with ID '" + slug + "'");
case 1: return destroyables.get(0);
default: throw new CommandException("Multiple destroyables have IDs that start with '" + slug + "'");
}
}));
}
private void assertEditPerms(CommandSender sender) throws CommandException {
if(!sender.hasPermission("pgm.destroyable.edit")) {
throw new CommandException("You don't have permission to do that");
}
}
@Command(
aliases = {"destroyable", "destroyables"},
desc = "Commands for working with destroyables (monuments)",
usage = "[id [completion[=(<blocks>|<percent>%)]]]",
min = 0,
max = -1
)
public void destroyable(CommandContext args, CommandSender sender) throws CommandException {
String id = args.getString(0, null);
if(id == null) {
list(args, sender);
} else {
Destroyable destroyable = lookup(CommandUtils.getMatch(sender), id);
String action = args.getString(1, null);
if(action == null) {
details(args, sender, destroyable);
} else if(action.startsWith("completion")) {
if(action.startsWith("completion=")) {
setCompletion(args, sender, destroyable, action.substring("completion=".length()));
}
completion(args, sender, destroyable);
} else {
throw new CommandException("Invalid action '" + action + "'");
}
}
}
public void list(CommandContext args, CommandSender sender) throws CommandException {
List<String> lines = new ArrayList<>();
lines.add(ChatColor.GRAY + "Destroyables");
for(Destroyable destroyable : matchModule().getDestroyables()) {
lines.add(" " + ChatColor.AQUA + destroyable.slug() +
": " + ChatColor.WHITE + destroyable.getName() +
ChatColor.GRAY + " owned by " + destroyable.getOwner().getColoredName());
}
sender.sendMessage(lines.toArray(new String[lines.size()]));
}
private String formatProperty(String name, Object value) {
return " " + ChatColor.GRAY + name + ChatColor.DARK_GRAY + ": " + ChatColor.WHITE + value;
}
public void details(CommandContext args, CommandSender sender, Destroyable destroyable) throws CommandException {
List<String> lines = new ArrayList<>();
lines.add(ChatColor.GRAY + "Destroyable " + ChatColor.AQUA + destroyable.slug());
lines.add(formatProperty("name", destroyable.getName()));
lines.add(formatProperty("owner", destroyable.getOwner().getColoredName()));
lines.add(formatProperty("size", destroyable.getMaxHealth()));
lines.add(formatProperty("completion", destroyable.getBreaksRequired() + " (" + destroyable.renderDestructionRequired() + ")"));
sender.sendMessage(lines.toArray(new String[lines.size()]));
}
public void completion(CommandContext args, CommandSender sender, Destroyable destroyable) throws CommandException {
sender.sendMessage(ChatColor.GRAY + "Destroyable " +
ChatColor.AQUA + destroyable.slug() +
ChatColor.GRAY + " has completion " +
ChatColor.WHITE + Math.round(destroyable.getDestructionRequired() * 100) + "%" +
ChatColor.GRAY + " or " +
ChatColor.WHITE + destroyable.getBreaksRequired() + "/" + destroyable.getMaxHealth() +
ChatColor.GRAY + " breaks");
}
public void setCompletion(CommandContext args, CommandSender sender, Destroyable destroyable, String value) throws CommandException {
assertEditPerms(sender);
Double completion;
Integer breaks;
if(value.endsWith("%")) {
completion = Double.parseDouble(value.substring(0, value.length() - 1)) / 100d;
breaks = null;
} else {
completion = null;
breaks = Integer.parseInt(value);
}
try {
if(completion != null) {
destroyable.setDestructionRequired(completion);
}
else if(breaks != null) {
destroyable.setBreaksRequired(breaks);
}
} catch(IllegalArgumentException e) {
throw new CommandException(e.getMessage());
}
}
}