/*
* This file is part of Kenshins Hide and Seek
*
* Copyright (c) 2021 Tyler Murphy.
*
* Kenshins Hide and Seek free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* he Free Software Foundation version 3.
*
* Kenshins Hide and Seek is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
package net.tylermurphy.hideAndSeek.command.util;
import net.tylermurphy.hideAndSeek.command.map.Save;
import net.tylermurphy.hideAndSeek.util.Pair;
import net.tylermurphy.hideAndSeek.util.Tuple;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.stream.Collectors;
import static net.tylermurphy.hideAndSeek.configuration.Config.errorPrefix;
import static net.tylermurphy.hideAndSeek.configuration.Config.permissionsRequired;
import static net.tylermurphy.hideAndSeek.configuration.Localization.message;
public class CommandGroup {
private final Map commandRegister;
private final String label;
public CommandGroup(String label, Object... data) {
this.label = label;
this.commandRegister = new LinkedHashMap<>();
for(Object o : data) {
registerCommand(o);
}
}
public String getLabel() {
return label;
}
private void registerCommand(Object object) {
if (object instanceof ICommand) {
ICommand command = (ICommand) object;
if (!commandRegister.containsKey(command.getLabel())) {
commandRegister.put(command.getLabel().toLowerCase(), command);
}
} else if(object instanceof CommandGroup) {
CommandGroup group = (CommandGroup) object;
if (!commandRegister.containsKey(group.getLabel())) {
commandRegister.put(group.getLabel().toLowerCase(), group);
}
}
}
public void handleCommand(Player player, String[] args) {
Tuple data = getCommand(args, this.getLabel());
if (data == null) {
player.sendMessage(
String.format("%s%sKenshin's Hide and Seek %s(%s1.7.0%s)\n", ChatColor.AQUA, ChatColor.BOLD, ChatColor.GRAY, ChatColor.WHITE, ChatColor.GRAY) +
String.format("%sAuthor: %s[KenshinEto]\n", ChatColor.GRAY, ChatColor.WHITE) +
String.format("%sHelp Command: %s/hs %shelp", ChatColor.GRAY, ChatColor.AQUA, ChatColor.WHITE)
);
return;
}
ICommand command = data.getLeft();
String permission = data.getCenter();
String[] parameters = data.getRight();
if (Save.runningBackup) {
player.sendMessage(errorPrefix + message("MAPSAVE_INPROGRESS"));
return;
}
if (permissionsRequired && !player.hasPermission(permission)) {
player.sendMessage(errorPrefix + message("COMMAND_NOT_ALLOWED"));
return;
}
int parameterCount = (int) Arrays.stream(command.getUsage().split(" ")).filter(p -> p.startsWith("<") && !p.startsWith("<*")).count();
if(parameters.length < parameterCount) {
player.sendMessage(errorPrefix + message("ARGUMENT_COUNT"));
return;
}
try {
command.execute(player, parameters);
} catch (Exception e) {
player.sendMessage(errorPrefix + "An error has occurred.");
e.printStackTrace();
}
}
@Nullable
private Tuple getCommand(String[] args, String permission) {
if(args.length < 1) {
return null;
}
String invoke = args[0];
if(commandRegister.containsKey(invoke)) {
Object o = commandRegister.get(invoke);
if (o instanceof CommandGroup) {
CommandGroup group = (CommandGroup) o;
return group.getCommand(
Arrays.copyOfRange(args, 1, args.length),
permission + "." + group.getLabel()
);
} else if(o instanceof ICommand) {
ICommand command = (ICommand) o;
return new Tuple<>(command, permission + "." + command.getLabel(), Arrays.copyOfRange(args, 1, args.length));
}
}
return null;
}
public List handleTabComplete(Player player, String[] args) {
return handleTabComplete(player, this.getLabel(), args);
}
private List handleTabComplete(Player player, String permission, String[] args) {
String invoke = args[0].toLowerCase();
if (args.length == 1) {
return new ArrayList<>(commandRegister.keySet())
.stream()
.filter(handle -> handle.toLowerCase().startsWith(invoke))
.filter(handle -> {
Object object = commandRegister.get(handle);
if (object instanceof ICommand) {
ICommand command = (ICommand) object;
return !permissionsRequired || player.hasPermission(permission + "." + command.getLabel());
} else if (object instanceof CommandGroup) {
CommandGroup group = (CommandGroup) object;
return !permissionsRequired || group.hasPermission(player, permission + "." + group.getLabel());
}
return false;
})
.collect(Collectors.toList());
} else {
if (commandRegister.containsKey(invoke)) {
Object object = commandRegister.get(invoke);
if (object instanceof CommandGroup) {
CommandGroup group = (CommandGroup) object;
return group.handleTabComplete(player, permission + "." + group.getLabel(), Arrays.copyOfRange(args, 1, args.length));
} else if (object instanceof ICommand) {
ICommand command = (ICommand) object;
String[] usage = command.getUsage().split(" ");
if (args.length - 2 < usage.length) {
String parameter = usage[args.length - 2];
String name = parameter.replace("<", "").replace(">", "");
List list = command.autoComplete(name, args[args.length - 1]);
if (list != null) {
return list;
}
}
}
}
return new ArrayList<>();
}
}
private boolean hasPermission(Player player, String permission) {
for(Object object : commandRegister.values()) {
if(object instanceof ICommand) {
ICommand command = (ICommand) object;
if(player.hasPermission(permission + command.getLabel())) return true;
} else if(object instanceof CommandGroup) {
CommandGroup group = (CommandGroup) object;
if (group.hasPermission(player, permission + this.label + ".")) return true;
}
}
return false;
}
public List> getCommands() {
return getCommands(this.getLabel());
}
private List> getCommands(String prefix) {
List> commands = new LinkedList<>();
for(Object object : commandRegister.values()) {
if(object instanceof ICommand) {
ICommand command = (ICommand) object;
commands.add(new Pair<>(prefix+" "+command.getLabel(), command));
} else if(object instanceof CommandGroup) {
CommandGroup group = (CommandGroup) object;
commands.addAll(group.getCommands(prefix+" "+group.getLabel()));
}
}
return commands;
}
}