@Override
  public boolean onCommand(
      final CommandSender sender, Command command, String commandName, String[] args) {
    CommandParser parser = new CommandParser(args);
    args = parser.getArgs();
    final boolean isSilent = parser.isSilent();

    if (isSilent && !sender.hasPermission(command.getPermission() + ".silent")) {
      sender.sendMessage(Message.getString("sender.error.noPermission"));
      return true;
    }

    if (args.length < 1) {
      return false;
    }

    if (CommandUtils.isValidNameDelimiter(args[0])) {
      CommandUtils.handleMultipleNames(sender, commandName, args);
      return true;
    }

    if (args[0].equalsIgnoreCase(sender.getName())) {
      sender.sendMessage(Message.getString("sender.error.noSelf"));
      return true;
    }

    String playerName = args[0];
    final Player player = plugin.getServer().getPlayer(playerName);

    if (player == null) {
      Message message = Message.get("sender.error.offline").set("[player]", playerName);

      sender.sendMessage(message.toString());
      return true;
    } else if (!sender.hasPermission("bm.exempt.override.kick")
        && player.hasPermission("bm.exempt.kick")) {
      Message.get("sender.error.exempt").set("player", player.getName()).sendTo(sender);
      return true;
    }

    final String reason = args.length > 1 ? CommandUtils.getReason(1, args).getMessage() : "";

    plugin
        .getServer()
        .getScheduler()
        .runTaskAsynchronously(
            plugin,
            new Runnable() {

              @Override
              public void run() {
                final PlayerData actor;

                if (sender instanceof Player) {
                  try {
                    actor =
                        plugin.getPlayerStorage().queryForId(UUIDUtils.toBytes((Player) sender));
                  } catch (SQLException e) {
                    sender.sendMessage(Message.get("sender.error.exception").toString());
                    e.printStackTrace();
                    return;
                  }
                } else {
                  actor = plugin.getPlayerStorage().getConsole();
                }

                final Message kickMessage;

                if (reason.isEmpty()) {
                  kickMessage = Message.get("kick.player.noReason");
                } else {
                  kickMessage = Message.get("kick.player.reason").set("reason", reason);
                }

                kickMessage
                    .set("displayName", player.getDisplayName())
                    .set("player", player.getName())
                    .set("playerId", player.getUniqueId().toString())
                    .set("actor", actor.getName());

                plugin
                    .getServer()
                    .getScheduler()
                    .runTask(
                        plugin,
                        new Runnable() {

                          @Override
                          public void run() {
                            player.kickPlayer(kickMessage.toString());

                            Message message =
                                Message.get(
                                    reason.isEmpty()
                                        ? "kick.notify.noReason"
                                        : "kick.notify.reason");
                            message
                                .set("player", player.getName())
                                .set("actor", actor.getName())
                                .set("reason", reason);

                            if (isSilent || !sender.hasPermission("bm.notify.kick")) {
                              message.sendTo(sender);
                            }

                            if (!isSilent)
                              CommandUtils.broadcast(message.toString(), "bm.notify.kick");
                          }
                        });
              }
            });

    return true;
  }
  @Override
  public boolean onCommand(
      final CommandSender sender, Command command, String commandName, String[] args) {
    CommandParser parser = new CommandParser(args);
    args = parser.getArgs();
    final boolean isSilent = parser.isSilent();

    if (isSilent && !sender.hasPermission(command.getPermission() + ".silent")) {
      sender.sendMessage(Message.getString("sender.error.noPermission"));
      return true;
    }

    if (args.length < 2) {
      return false;
    }

    if (CommandUtils.isValidNameDelimiter(args[0])) {
      CommandUtils.handleMultipleNames(sender, commandName, args);
      return true;
    }

    if (args[0].equalsIgnoreCase(sender.getName())) {
      sender.sendMessage(Message.getString("sender.error.noSelf"));
      return true;
    }

    // Check if UUID vs name
    final String playerName = args[0];
    final boolean isUUID = playerName.length() > 16;

    Player onlinePlayer;

    if (isUUID) {
      onlinePlayer = plugin.getServer().getPlayer(UUID.fromString(playerName));
    } else {
      onlinePlayer = plugin.getServer().getPlayer(playerName);
    }

    if (onlinePlayer == null) {
      if (!sender.hasPermission("bm.command.report.offline")) {
        sender.sendMessage(Message.getString("sender.error.offlinePermission"));
        return true;
      }
    } else if (!sender.hasPermission("bm.exempt.override.report")
        && onlinePlayer.hasPermission("bm.exempt.report")) {
      Message.get("sender.error.exempt").set("player", onlinePlayer.getName()).sendTo(sender);
      return true;
    }

    final String reason = CommandUtils.getReason(1, args);

    plugin
        .getServer()
        .getScheduler()
        .runTaskAsynchronously(
            plugin,
            new Runnable() {

              @Override
              public void run() {
                final PlayerData player = CommandUtils.getPlayer(sender, playerName);

                if (player == null) {
                  sender.sendMessage(
                      Message.get("sender.error.notFound").set("player", playerName).toString());
                  return;
                }

                if (plugin.getExemptionsConfig().isExempt(player, "ban")) {
                  sender.sendMessage(
                      Message.get("sender.error.exempt").set("player", playerName).toString());
                  return;
                }

                try {
                  if (plugin.getPlayerReportStorage().isRecentlyReported(player)) {
                    Message.get("report.error.cooldown").sendTo(sender);
                    return;
                  }
                } catch (SQLException e) {
                  sender.sendMessage(Message.get("sender.error.exception").toString());
                  e.printStackTrace();
                  return;
                }

                final PlayerData actor = CommandUtils.getActor(sender);

                if (actor == null) return;

                PlayerReportData report = new PlayerReportData(player, actor, reason);

                try {
                  plugin.getPlayerReportStorage().report(report, isSilent);
                } catch (SQLException e) {
                  sender.sendMessage(Message.get("sender.error.exception").toString());
                  e.printStackTrace();
                }
              }
            });

    return true;
  }