@Override
  public boolean execute(CommandSender sender, ArrayList<String> args) {
    if (!sender.hasPermission("bw." + this.getPermission())) {
      return false;
    }

    Player player = (Player) sender;

    Game game = this.getPlugin().getGameManager().getGame(args.get(0));
    String name = args.get(1).toString();

    if (game == null) {
      player.sendMessage(
          ChatWriter.pluginMessage(
              ChatColor.RED
                  + Main._l(
                      "errors.gamenotfound", ImmutableMap.of("game", args.get(0).toString()))));
      return false;
    }

    if (game.getState() == GameState.RUNNING) {
      sender.sendMessage(
          ChatWriter.pluginMessage(ChatColor.RED + Main._l("errors.notwhilegamerunning")));
      return false;
    }

    if (name.length() > 15) {
      player.sendMessage(
          ChatWriter.pluginMessage(ChatColor.RED + Main._l("errors.toolongregionname")));
      return true;
    }

    game.setRegionName(name);
    player.sendMessage(
        ChatWriter.pluginMessage(ChatColor.GREEN + Main._l("success.regionnameset")));
    return true;
  }
  @EventHandler
  public void onPlayerInteract(PlayerInteractEvent pie) {
    Player player = pie.getPlayer();
    Game g = Main.getInstance().getGameManager().getGameOfPlayer(player);

    if (g == null) {
      if (pie.getAction() != Action.RIGHT_CLICK_BLOCK
          && pie.getAction() != Action.RIGHT_CLICK_AIR) {
        return;
      }

      Block clicked = pie.getClickedBlock();

      if (clicked == null) {
        return;
      }

      if (!(clicked.getState() instanceof Sign)) {
        return;
      }

      Game game = Main.getInstance().getGameManager().getGameBySignLocation(clicked.getLocation());
      if (game == null) {
        return;
      }

      if (game.playerJoins(player)) {
        player.sendMessage(ChatWriter.pluginMessage(ChatColor.GREEN + Main._l("success.joined")));
      }
      return;
    }

    if (g.getState() == GameState.STOPPED) {
      return;
    }

    Material interactingMaterial = pie.getMaterial();
    Block clickedBlock = pie.getClickedBlock();

    if (g.getState() == GameState.RUNNING) {
      if (pie.getAction() == Action.PHYSICAL) {
        if (clickedBlock != null
            && (clickedBlock.getType() == Material.WHEAT
                || clickedBlock.getType() == Material.SOIL)) {
          pie.setCancelled(true);
          return;
        }
      }

      if (pie.getAction() != Action.RIGHT_CLICK_BLOCK
          && pie.getAction() != Action.RIGHT_CLICK_AIR) {
        return;
      }

      if (clickedBlock != null) {
        if (clickedBlock.getType() == Material.LEVER
            && !g.isSpectator(player)
            && pie.getAction() == Action.RIGHT_CLICK_BLOCK) {
          if (!g.getRegion().isPlacedUnbreakableBlock(clickedBlock)) {
            g.getRegion().addPlacedUnbreakableBlock(clickedBlock, clickedBlock.getState());
          }
          return;
        }
      }

      if (g.isSpectator(player)) {
        if (interactingMaterial == Material.SLIME_BALL) {
          g.playerLeave(player, false);
          return;
        }

        if (interactingMaterial == Material.COMPASS) {
          g.openSpectatorCompass(player);
          pie.setCancelled(true);
          return;
        }
      }

      // Spectators want to block
      if (clickedBlock != null) {
        try {
          GameMode.valueOf("SPECTATOR");
        } catch (Exception ex) {
          for (Player p : g.getFreePlayers()) {
            if (!g.getRegion().isInRegion(p.getLocation())) {
              continue;
            }

            if (pie.getClickedBlock().getLocation().distance(p.getLocation()) < 2) {
              Location oldLocation = p.getLocation();
              if (oldLocation.getY() >= pie.getClickedBlock().getLocation().getY()) {
                oldLocation.setY(oldLocation.getY() + 2);
              } else {
                oldLocation.setY(oldLocation.getY() - 2);
              }

              p.teleport(oldLocation);
            }
          }
        }
      }

      if (clickedBlock != null) {
        if (clickedBlock.getType() == Material.ENDER_CHEST && !g.isSpectator(player)) {
          pie.setCancelled(true);

          Block chest = pie.getClickedBlock();
          Team chestTeam = g.getTeamOfEnderChest(chest);
          Team playerTeam = g.getPlayerTeam(player);

          if (chestTeam == null) {
            return;
          }

          if (chestTeam.equals(playerTeam)) {
            player.openInventory(chestTeam.getInventory());
          } else {
            player.sendMessage(
                ChatWriter.pluginMessage(ChatColor.RED + Main._l("ingame.noturteamchest")));
          }

          return;
        }
      }

      return;
    } else if (g.getState() == GameState.WAITING) {
      if (interactingMaterial == null) {
        pie.setCancelled(true);
        return;
      }

      if (pie.getAction() == Action.PHYSICAL) {
        if (clickedBlock != null
            && (clickedBlock.getType() == Material.WHEAT
                || clickedBlock.getType() == Material.SOIL)) {
          pie.setCancelled(true);
          return;
        }
      }

      if (pie.getAction() != Action.RIGHT_CLICK_BLOCK
          && pie.getAction() != Action.RIGHT_CLICK_AIR) {
        return;
      }

      switch (interactingMaterial) {
        case BED:
          pie.setCancelled(true);
          if (!g.isAutobalanceEnabled()) {
            g.getPlayerStorage(player).openTeamSelection(g);
          }

          break;
        case DIAMOND:
          pie.setCancelled(true);
          if (player.isOp() || player.hasPermission("bw.setup")) {
            g.start(player);
          } else if (player.hasPermission("bw.vip.forcestart")) {
            GameLobbyCountdownRule rule = Main.getInstance().getLobbyCountdownRule();
            if (rule.isRuleMet(g)) {
              g.start(player);
            } else {
              if (rule == GameLobbyCountdownRule.PLAYERS_IN_GAME
                  || rule == GameLobbyCountdownRule.ENOUGH_TEAMS_AND_PLAYERS) {
                player.sendMessage(
                    ChatWriter.pluginMessage(
                        ChatColor.RED + Main._l("lobby.notenoughplayers-rule0")));
              } else {
                player.sendMessage(
                    ChatWriter.pluginMessage(
                        ChatColor.RED + Main._l("lobby.notenoughplayers-rule1")));
              }
            }
          }
          break;
        case SLIME_BALL:
          pie.setCancelled(true);
          g.playerLeave(player, false);
          break;
        case LEATHER_CHESTPLATE:
          pie.setCancelled(true);
          player.updateInventory();
          break;
        default:
          break;
      }
    }
  }
  @EventHandler(priority = EventPriority.HIGH)
  public void onInteractEntity(PlayerInteractEntityEvent event) {
    if (event.getRightClicked() == null) {
      return;
    }

    Entity entity = event.getRightClicked();
    Player player = event.getPlayer();
    if (!player.hasMetadata("bw-addteamjoin")) {
      if (!(entity instanceof LivingEntity)) {
        return;
      }

      LivingEntity livEntity = (LivingEntity) entity;
      Game game = Main.getInstance().getGameManager().getGameOfPlayer(player);
      if (game == null) {
        return;
      }

      if (game.getState() != GameState.WAITING) {
        return;
      }

      Team team = game.getTeam(ChatColor.stripColor(livEntity.getCustomName()));
      if (team == null) {
        return;
      }

      game.playerJoinTeam(player, team);
      event.setCancelled(true);
      return;
    }

    List<MetadataValue> values = player.getMetadata("bw-addteamjoin");
    if (values == null || values.size() == 0) {
      return;
    }

    event.setCancelled(true);
    TeamJoinMetaDataValue value = (TeamJoinMetaDataValue) values.get(0);
    if (!((boolean) value.value())) {
      return;
    }

    if (!(entity instanceof LivingEntity)) {
      player.sendMessage(
          ChatWriter.pluginMessage(ChatColor.RED + Main._l("errors.entitynotcompatible")));
      return;
    }

    LivingEntity living = (LivingEntity) entity;
    living.setRemoveWhenFarAway(false);
    living.setCanPickupItems(false);
    living.setCustomName(value.getTeam().getChatColor() + value.getTeam().getDisplayName());
    living.setCustomNameVisible(
        Main.getInstance().getBooleanConfig("jointeam-entity.show-name", true));

    if (Utils.isSupportingTitles()) {
      if (living.getType().equals(EntityType.valueOf("ARMOR_STAND"))) {
        Utils.equipArmorStand(living, value.getTeam());
      }
    }

    player.removeMetadata("bw-addteamjoin", Main.getInstance());
    player.sendMessage(
        ChatWriter.pluginMessage(
            ChatColor.GREEN
                + Main._l(
                    "success.teamjoinadded",
                    ImmutableMap.of(
                        "team",
                        value.getTeam().getChatColor()
                            + value.getTeam().getDisplayName()
                            + ChatColor.GREEN))));
  }