package net.anxuiz.tourney.command;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.sk89q.bukkit.util.BukkitWrappedCommandSender;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.minecraft.util.commands.NestedCommand;
import net.anxuiz.tourney.ClassificationManager;
import net.anxuiz.tourney.MapClassification;
import net.anxuiz.tourney.TeamManager;
import net.anxuiz.tourney.Tourney;
import net.anxuiz.tourney.TourneyState;
import net.anxuiz.tourney.vote.VoteContext;
import org.apache.commons.collections.CollectionUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import tc.oc.api.docs.Entrant;
import tc.oc.commons.bukkit.commands.PrettyPaginatedResult;
import tc.oc.commons.core.commands.NestedCommands;
import tc.oc.pgm.commands.CommandUtils;
import tc.oc.pgm.map.MapInfo;
import tc.oc.pgm.map.PGMMap;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.match.inject.MatchScoped;
import static tc.oc.commons.core.exception.LambdaExceptionUtils.rethrowConsumer;
@MatchScoped
public class MapSelectionCommands implements NestedCommands {
private final Tourney tourney;
private final TeamManager teamManager;
private final VoteContext voteContext;
private final ClassificationManager classificationManager;
private final Match match;
@Inject MapSelectionCommands(Tourney tourney, TeamManager teamManager, VoteContext voteContext, ClassificationManager classificationManager, Match match) {
this.tourney = tourney;
this.teamManager = teamManager;
this.voteContext = voteContext;
this.classificationManager = classificationManager;
this.match = match;
}
@Command(
aliases = {"options", "remaining"},
desc = "Displays remaining classifications or maps.",
min = 0,
max = 1,
usage = "[page]"
)
@Console
@CommandPermissions("tourney.map.veto")
public void options(CommandContext args, CommandSender sender) throws CommandException {
if (!tourney.getState().equals(TourneyState.ENABLED_MAP_SELECTION)) {
throw new CommandException("There is no map selection vote in progress.");
}
voteContext.currentVote().ifPresent(rethrowConsumer(vote -> {
if (vote.getSelectedClassification() != null) {
new PrettyPaginatedResult<PGMMap>("Remaining Maps") {
@Override
public String format(PGMMap entry, int index) {
MapInfo info = entry.getInfo();
return org.bukkit.ChatColor.DARK_AQUA + "" + info.name + org.bukkit.ChatColor.GRAY + " " + info.version;
}
}.display(new BukkitWrappedCommandSender(sender), vote.getRemainingMaps(), args.argsLength() > 0 ? args.getInteger(0) : 1);
} else {
final Set<PGMMap> remainingMaps = vote.getRemainingMaps();
new PrettyPaginatedResult<MapClassification>("Remaining Classifications") {
@Override
public String format(MapClassification entry, int index) {
return org.bukkit.ChatColor.DARK_AQUA + "" + entry.name() + org.bukkit.ChatColor.GRAY + " (" + CollectionUtils.intersection(entry.maps(), remainingMaps).size() + " maps)";
}
}.display(new BukkitWrappedCommandSender(sender), vote.getRemainingClassifications(), args.argsLength() > 0 ? args.getInteger(0) : 1);
}
}));
}
@Command(
aliases = "veto",
desc = "Vetoes a map or classification, indicating that it is the least desired of all available options.",
min = 1,
max = -1
)
@CommandPermissions("tourney.map.veto")
public void veto(CommandContext args, CommandSender sender) throws CommandException {
if (!(sender instanceof Player)) throw new CommandException("You must be a player to use this command.");
if (!tourney.getState().equals(TourneyState.ENABLED_MAP_SELECTION)) {
throw new CommandException("There is no map selection vote in progress.");
}
voteContext.currentVote().ifPresent(rethrowConsumer(vote -> {
MatchPlayer player = match.getPlayer((Player) sender);
Entrant participation = teamManager.teamToEntrant(player.getParty());
if (participation == null) throw new CommandException("You are not participating in this veto.");
if (!vote.getCurrentTurnRemainingTeams().contains(participation)) {
throw new CommandException("You have already cast your veto for this turn.");
}
if (vote.getSelectedClassification() == null) {
MapClassification classification = classificationManager.classificationFromSearch(args.getJoinedStrings(0));
if (classification == null) throw new CommandException("No classification matched query.");
if (!vote.getRemainingClassifications().contains(classification)) {
throw new CommandException("Specified classification is no longer available.");
}
try {
vote.registerVeto(participation, classification);
} catch (IllegalArgumentException e) {
throw new CommandException(e.getMessage());
}
} else {
PGMMap map = CommandUtils.getMap(args.getJoinedStrings(0));
try {
vote.registerVeto(participation, map);
} catch (IllegalArgumentException e) {
throw new CommandException(e.getMessage());
}
}
}));
}
@Command(
aliases = {"beginvote", "startvote"},
desc = "Begins a map selection vote.",
min = 0,
max = 0,
flags = "ct:"
)
@Console
@CommandPermissions("tourney.map.beginvote")
public void beginVote(CommandContext args, CommandSender sender) throws CommandException {
if (!tourney.getState().equals(TourneyState.ENABLED_WAITING_FOR_READY)) {
throw new CommandException("This match is not in a state that is eligible for map selection.");
} else if (voteContext.voteInProgress()) {
throw new CommandException("There is already a map selection vote in progress.");
} else if (!args.hasFlag('c')) {
throw new CommandException("Re-run command with -c to confirm. Map selection may not be ended pre-maturely.");
}
if (args.hasFlag('t')) {
MapClassification classification = classificationManager.classificationFromSearch(args.getFlag('t'));
if (classification == null) throw new CommandException("No classification matched query.");
voteContext.startVote(Collections.singleton(classification));
} else {
voteContext.startVote(classificationManager.getClassifications());
}
}
@Singleton
public static class MapSelectionParentCommand implements NestedCommands {
private final Tourney tourney;
@Inject MapSelectionParentCommand(Tourney tourney) {
this.tourney = tourney;
}
@Command(
aliases = {"map", "mapselection"},
desc = "Map selection-related commands"
)
@NestedCommand(value = MapSelectionCommands.class, executeBody = true)
public void mapSelectionParentCommand(final CommandContext args, final CommandSender sender) throws CommandException {
if (!Arrays.asList(TourneyState.ENABLED_MAP_SELECTION, TourneyState.ENABLED_WAITING_FOR_READY).contains(tourney.getState())) {
throw new CommandException("This match is not in a state that is eligible for map selection.");
}
}
}
}