package jk_5.nailed.server.command;
import jk_5.nailed.api.command.CommandCallable;
import jk_5.nailed.api.command.CommandException;
import jk_5.nailed.api.command.CommandMapping;
import jk_5.nailed.api.command.completion.CommandCompleter;
import jk_5.nailed.api.command.context.CommandLocals;
import jk_5.nailed.api.command.dispatcher.Dispatcher;
import jk_5.nailed.api.command.parametric.ParameterData;
import jk_5.nailed.api.command.parametric.ParametricCallable;
import jk_5.nailed.api.command.parametric.binding.BindingBehavior;
import jk_5.nailed.api.command.sender.CommandSender;
import jk_5.nailed.api.command.sender.MapCommandSender;
import jk_5.nailed.api.map.Map;
import jk_5.nailed.api.map.Team;
import jk_5.nailed.api.player.Player;
import jk_5.nailed.server.NailedPlatform;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class NailedCommandCompleter implements CommandCompleter {
private static final Logger logger = LogManager.getLogger();
private static Field parameters;
Dispatcher dispatcher;
static {
try{
parameters = ParametricCallable.class.getDeclaredField("parameters");
parameters.setAccessible(true);
}catch(NoSuchFieldException e){
logger.warn("Was not able to find parameters field in ParametricCallable");
parameters = null;
}
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
String input = (String) locals.get("CMD_INPUT");
String inputPath = input.substring(0, input.length() - arguments.length()).trim();
String partialInput = input.substring(input.lastIndexOf(' ') + 1);
String path = input.substring(0, input.lastIndexOf(' '));
List<String> out = new ArrayList<String>();
String[] split = inputPath.split(" ", -1);
String[] splitInput = arguments.split(" " , -1);
CommandMapping p = dispatcher.get(inputPath);
Dispatcher disp = dispatcher;
ParameterData[] paramData = new ParameterData[0];
for(int i = 0; i < split.length; i++){
CommandCallable callable = disp.get(split[i]).getCallable();
if(callable instanceof Dispatcher){
disp = (Dispatcher) callable;
}else if(callable instanceof ParametricCallable){
try{
paramData = (ParameterData[]) parameters.get(callable);
break;
}catch(IllegalAccessException e){
//I don't care
}
}else{
break;
}
}
List<ParameterData> realParamsBuilder = new ArrayList<ParameterData>();
for(ParameterData pd : paramData){
if(pd.getBinding().getBehavior(pd) != BindingBehavior.PROVIDES){
realParamsBuilder.add(pd);
}
}
ParameterData[] realParams = realParamsBuilder.toArray(new ParameterData[realParamsBuilder.size()]);
ParameterData completingParam = realParams.length >= splitInput.length ? realParams[splitInput.length - 1] : null;
if(completingParam == null) return out;
String completingName = completingParam.getName();
if(completingName.equals("gamemode")){
out.add("survival");
out.add("creative");
out.add("adventure");
out.add("spectator");
}else if(completingName.equals("difficulty")){
out.add("peaceful");
out.add("easy");
out.add("medium");
out.add("hard");
}else if(completingName.equals("weathertype")){
out.add("clear");
out.add("dry");
out.add("rain");
out.add("thunder");
}else if(completingName.equals("mappack")){
out.addAll(NailedPlatform.instance().getMappackRegistry().getAllIds());
}else if(completingName.equals("player")){
for(Player pl : NailedPlatform.instance().getOnlinePlayers()){
out.add(pl.getName());
}
}else if(completingName.equals("team")){
CommandSender sender = locals.get(CommandSender.class);
if(sender instanceof MapCommandSender){
Map map = ((MapCommandSender) sender).getMap();
if(map != null){
for(Team team : map.getTeams()){
out.add(team.id());
}
}
}
}else if(completingName.equals("gamewinnable")){
CommandSender sender1 = locals.get(CommandSender.class);
if(sender1 instanceof MapCommandSender){
Map map = ((MapCommandSender) sender1).getMap();
if(map != null){
for(Team team : map.getTeams()){
out.add(team.id());
}
}
}
for(Player pl : NailedPlatform.instance().getOnlinePlayers()){
out.add(pl.getName());
}
}
List<String> ret = new ArrayList<String>();
for(String s : out){
if(s.toLowerCase().startsWith(partialInput.toLowerCase())){
ret.add(s);
}
}
return ret;
}
}