package tc.oc.commons.bukkit.inventory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import tc.oc.commons.bukkit.item.ItemUtils;
public class InventoryUtils {
private InventoryUtils() {}
public static Inventory clickedInventory(InventoryClickEvent event) {
return event.getSlot() == event.getRawSlot() ? event.getView().getTopInventory()
: event.getView().getBottomInventory();
}
public static <I extends Inventory, S extends Slot<I, ?>> Stream<? extends S> similar(I inv, Stream<? extends S> slots, ItemStack stack) {
return slots.filter(slot -> stack.isSimilar(slot.getItem(inv)));
}
public static <I extends Inventory, S extends Slot<I, ?>> Stream<? extends S> empty(I inv, Stream<? extends S> slots) {
return slots.filter(slot -> ItemUtils.isNothing(slot.getItem(inv)));
}
public static Stream<? extends Slot.Storage> similar(PlayerInventory inv, ItemStack stack) {
return similar(inv, Slot.Storage.storage(), stack);
}
public static Stream<? extends Slot.Storage> empty(PlayerInventory inv) {
return empty(inv, Slot.Storage.storage());
}
public static Stream<ItemStack> contents(Inventory inventory) {
// Do this without calling getContents(), because it create a temp array
final Stream.Builder<ItemStack> builder = Stream.builder();
for(int i = 0; i < inventory.getSize(); i++) {
final ItemStack item = inventory.getItem(i);
if(!ItemUtils.isNothing(item)) {
builder.add(item);
}
}
return builder.build();
}
public static <I extends Inventory, S extends Slot<I, ?>> Map<S, ItemStack> chooseSlots(I inv, Stream<? extends S> slots, ItemStack stack) {
final Map<S, ItemStack> map = new HashMap<>();
final ItemStack remaining = stack.clone();
final List<? extends S> slotList = slots.collect(Collectors.toList());
Stream.<S>concat(similar(inv, slotList.stream(), remaining), empty(inv, slotList.stream())).forEach(slot -> {
if(!ItemUtils.isNothing(remaining)) {
final int transferAmount = slot.maxTransferrableIn(remaining, inv);
if(transferAmount > 0) {
final ItemStack transferStack = remaining.clone();
remaining.setAmount(remaining.getAmount() - transferAmount);
transferStack.setAmount(transferAmount);
map.put(slot, transferStack);
}
}
});
return map;
}
public static Map<Slot.Storage, ItemStack> chooseStorageSlots(PlayerInventory inv, ItemStack stack) {
return chooseSlots(inv, Slot.Storage.storage(), stack);
}
}