package com.legendzero.lzlib.command.arg;

import com.google.common.collect.Lists;
import com.legendzero.lzlib.command.CommandContext;
import com.legendzero.lzlib.command.SubCommand;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

public class PlayerArg implements CommandArg {

    public static BiPredicate<? super CommandSender, ? super Player> EXCLUDE_SELF
            = (sender, player) -> sender != player;
    public static BiPredicate<? super CommandSender, ? super Player> CAN_SEE
            = (sender, player) -> (sender instanceof Player) && ((Player) sender).canSee(player);

    private final String contextKey;
    private final boolean infinite;
    private final BiPredicate<? super CommandSender, ? super Player> predicate;

    public PlayerArg(String contextKey) {
        this(contextKey, false);
    }

    public PlayerArg(String contextKey, boolean infinite) {
        this(contextKey, infinite, (s, p) -> true);
    }

    public PlayerArg(String contextKey,
                     BiPredicate<? super CommandSender, ? super Player> predicate) {
        this(contextKey, false, predicate);
    }

    public PlayerArg(String contextKey, boolean infinite,
                     BiPredicate<? super CommandSender, ? super Player> predicate) {
        this.contextKey = contextKey;
        this.infinite = infinite;
        this.predicate = predicate;
    }

    public Status execute(SubCommand command, CommandContext context) {
        if (this.infinite) {
            List<Player> players = Lists.newArrayList();
            while (context.hasNextArgument()) {
                String argument = context.nextArgument();
                Player player = Bukkit.getPlayer(argument);
                if (player != null && this.predicate.test(context.getSender(), player)) {
                    players.add(player);
                } else {
                    context.previousArgument();
                }
            }
            context.putContext(this.contextKey, players);
            if (players.size() > 0) {
                return Status.PARSED_ARGUMENTS;
            } else {
                return Status.SKIPPED_ARGUMENTS;
            }
        }
        if (context.hasNextArgument()) {
            String argument = context.nextArgument();
            Player player = Bukkit.getPlayer(argument);
            if (player != null && this.predicate.test(context.getSender(), player)) {
                context.putContext(this.contextKey, player);
                context.markArgument();
                return Status.PARSED_ARGUMENTS;
            } else {
                return Status.INVALID_ARGUMENTS;
            }
        }
        return Status.NOT_ENOUGH_ARGUMENTS;
    }

    @Override
    public List<String> tabComplete(SubCommand command, CommandContext context) {
        String prefix = context.hasNextArgument() ? context.peekArgument() : "";
        return Bukkit.getOnlinePlayers().stream().filter(player
                -> this.predicate.test(context.getSender(), player))
                .map(Player::getName).filter(name
                        -> name.startsWith(prefix))
                .collect(Collectors.toList());
    }
}

@@ -206,49 +206,8 @@
 it;%0A
-import org.bukkit.command.CommandSender;%0A
 impo
@@ -420,38 +420,39 @@
 %3C? super Command
-Sender
+Context
 , ? super Player
@@ -473,38 +473,39 @@
 %0A            = (
-sender
+context
 , player) -%3E sen
@@ -501,22 +501,35 @@
 yer) -%3E 
-s
+context.getS
 ender
+()
  != play
@@ -569,38 +569,39 @@
 %3C? super Command
-Sender
+Context
 , ? super Player
@@ -625,22 +625,23 @@
      = (
-sender
+context
 , player
@@ -646,22 +646,35 @@
 er) -%3E (
-s
+context.getS
 ender
+()
  instanc
@@ -684,16 +684,28 @@
  Player)
+%0A           
  && ((Pl
@@ -714,14 +714,27 @@
 er) 
-s
+context.getS
 ender
+()
 ).ca
@@ -858,38 +858,39 @@
 %3C? super Command
-Sender
+Context
 , ? super Player
@@ -1184,38 +1184,39 @@
 %3C? super Command
-Sender
+Context
 , ? super Player
@@ -1387,22 +1387,23 @@
  Command
-Sender
+Context
 , ? supe
@@ -1925,36 +1925,24 @@
 test(context
-.getSender()
 , player)) %7B
@@ -2534,36 +2534,24 @@
 test(context
-.getSender()
 , player)) %7B
@@ -3132,28 +3132,16 @@
 (context
-.getSender()
 , player

Use CommandContext as predicate type to supply better access.