/*
   * Internal method to execute tab auto-completion.
   */
  @Override
  public List<String> onTabComplete(
      CommandSender sender, Command command, String label, String[] originalArgs) {
    if (originalArgs.length == 1) {
      // Searching for a subcommand
      List<String> matches = new ArrayList<String>();

      for (BaseCommand baseCommand : plugin.getCommands().getRegistrations()) {
        if (StringUtil.startsWithIgnoreCase(baseCommand.getName(), originalArgs[0])
            && baseCommand.hasPermission(sender)) {
          matches.add(baseCommand.getName());
        }
      }
      return matches;
    } else if (originalArgs.length > 1) {
      // Searching in a subcommand
      BaseCommand baseCommand = plugin.getCommands().getRegistration(originalArgs[0]);
      if (baseCommand != null && baseCommand.hasPermission(sender)) {
        String[] args = new String[originalArgs.length - 1];
        System.arraycopy(originalArgs, 1, args, 0, originalArgs.length - 1);
        return baseCommand.autoComplete(sender, args);
      }
    }

    return Collections.emptyList();
  }
  public BetterEnderCommandManager(BetterEnderChest plugin) {
    this.plugin = plugin;

    Registry<BaseCommand> commands = plugin.getCommands();
    commands.register(new DeleteInvCommand(plugin));
    commands.register(new GiveCommand(plugin));
    commands.register(new ListCommand(plugin));
    commands.register(new OpenInvCommand(plugin));
    commands.register(new ReloadCommand(plugin));
    commands.register(new SwapInvCommand(plugin));
    commands.register(new ViewInvCommand(plugin));
  }
  /*
   * Internal method to execute the command.
   */
  @Override
  public boolean onCommand(
      CommandSender sender, Command bukkitCommand, String label, String[] originalArgs) {
    // Handle the /betterenderchest command
    if (originalArgs.length == 0) {
      showHelp(sender, label);
      return true;
    }

    String name = originalArgs[0];

    // Copy to new array, move all arguments one postion
    // So ["give","Notch","GOLDEN_APPLE","64"] gets
    // ["Notch","GOLDEN_APPLE","64"]
    String[] args = new String[originalArgs.length - 1];
    for (int i = 1; i < originalArgs.length; i++) {
      args[i - 1] = originalArgs[i];
    }

    BaseCommand command = plugin.getCommands().getRegistration(originalArgs[0]);

    if (command == null) {
      sender.sendMessage(ChatColor.RED + "Command " + name + " not found... Available commands:");
      showHelp(sender, label);
      return true;
    }

    if (!command.hasPermission(sender)) {
      sender.sendMessage("" + ChatColor.RED + Translations.NO_PERMISSION);
      return true;
    }

    if (!command.execute(sender, args)) {
      sender.sendMessage(ChatColor.RED + "Wrong command usage! Correct usage:");
      sender.sendMessage(ChatColor.RED + "/" + label + " " + name + " " + command.getUsage());
      return true;
    }

    return true;
  }
  /*
   * Internal method to show a list of commands along with their usage.
   */
  private void showHelp(CommandSender sender, String label) {
    Collection<BaseCommand> commands = plugin.getCommands().getRegistrations();
    int commandCount = 0; // Counts available commands

    for (BaseCommand command : commands) {
      if (command.hasPermission(sender)) {
        if (!command.getUsage().equals("")) {
          // Only display usage message if it has one
          sender.sendMessage(
              ChatColor.GOLD
                  + "/"
                  + label
                  + " "
                  + command.getName()
                  + " "
                  + command.getUsage()
                  + ": "
                  + ChatColor.WHITE
                  + command.getHelpText());
        } else {
          sender.sendMessage(
              ChatColor.GOLD
                  + "/"
                  + label
                  + " "
                  + command.getName()
                  + ": "
                  + ChatColor.WHITE
                  + command.getHelpText());
        }

        commandCount++;
      }
    }

    if (commandCount == 0) {
      sender.sendMessage(ChatColor.GOLD + "Sorry, no available commands for your rank.");
    }
  }
  @Override
  public Inventory importInventory(
      ChestOwner chestOwner, WorldGroup worldGroup, BetterEnderChest plugin) throws IOException {
    // Cannot import vanilla chests
    if (chestOwner.isSpecialChest()) {
      return null;
    }

    Player player = chestOwner.getPlayer();
    Inventory betterEnderInventory;
    if (player == null) {

      // Offline, load from file
      File playerDirectory =
          new File(Bukkit.getWorlds().get(0).getWorldFolder().getAbsolutePath() + "/playerdata");

      File playerFile =
          new File(playerDirectory.getAbsolutePath() + "/" + chestOwner.getSaveFileName() + ".dat");
      if (!playerFile.exists()) {
        return null;
      }

      // Load it from the file (mainworld/playerdata/playername.dat)
      betterEnderInventory =
          plugin
              .getNMSHandlers()
              .getSelectedRegistration()
              .loadNBTInventoryFromFile(playerFile, chestOwner, worldGroup, "EnderItems");
      if (betterEnderInventory == null) {
        // Cannot load the inventory from that file, most likely because
        // it is empty
        return null;
      }
    } else {
      // Online, load now
      Inventory vanillaInventory = player.getEnderChest();
      int inventoryRows =
          plugin.getEmptyInventoryProvider().getInventoryRows(chestOwner, vanillaInventory);
      betterEnderInventory =
          plugin
              .getEmptyInventoryProvider()
              .loadEmptyInventory(
                  chestOwner,
                  worldGroup,
                  inventoryRows,
                  plugin.getChestSizes().getDisabledSlots(player));

      // Copy all items
      ListIterator<ItemStack> copyIterator = vanillaInventory.iterator();
      while (copyIterator.hasNext()) {
        int slot = copyIterator.nextIndex();
        ItemStack stack = copyIterator.next();
        if (slot < betterEnderInventory.getSize()) {
          betterEnderInventory.setItem(slot, stack);
        }
      }
    }

    // Check if the inventory is empty
    if (BetterEnderUtils.isInventoryEmpty(betterEnderInventory)) {
      // Empty inventory, return null
      return null;
    } else {
      // Return the inventory
      return betterEnderInventory;
    }
  }