package me.km.inventory;

import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;

public class InventoryUtils {
    public static int searchInventoryFor(IInventory inv, ItemStack searchfor, boolean useData) {
        if(searchfor.isEmpty()) {
            return 0;
        }
        int counter = 0;
        if(useData) {
            int size = inv.getSizeInventory();
            ItemStack stack;
            for(int i = 0; i < size; i++) {
                stack = inv.getStackInSlot(i);
                if(stackEqualExact(stack, searchfor)) {
                    counter += stack.getCount();
                }
            }
        } else {
            int size = inv.getSizeInventory();
            Item item = searchfor.getItem();
            ItemStack stack;
            for(int i = 0; i < size; i++) {
                stack = inv.getStackInSlot(i);
                if(stack.getItem() == item) {
                    counter += stack.getCount();
                }
            }
        }
        return counter;
    }

    public static int removeFromInventory(IInventory inv, ItemStack remove) {
        if(remove.isEmpty()) {
            return 0;
        }
        ItemStack stack;
        int sub;
        int amount = remove.getCount();
        for(int i = 0; i < inv.getSizeInventory(); i++) {
            stack = inv.getStackInSlot(i);
            if(stackEqualExact(stack, remove)) {
                sub = stack.getCount();
                if(amount > sub) {
                    amount -= sub;
                    inv.setInventorySlotContents(i, ItemStack.EMPTY);
                } else if(amount == sub) {
                    inv.setInventorySlotContents(i, ItemStack.EMPTY);
                    return 0;
                } else {
                    stack.setCount(sub - amount);
                    return 0;
                }
            }
        }
        return amount;
    }

    public static int addToInventory(IInventory inv, ItemStack add) {
        if(add.isEmpty()) {
            return 0;
        } else {
            if(add.isDamaged()) {
                int j = getFirstEmptyStack(inv);
                if(j >= 0) {
                    inv.setInventorySlotContents(j, add.copy());
                    inv.getStackInSlot(j).setAnimationsToGo(5);
                    return 0;
                }
                return add.getCount();
            } else {
                ItemStack copy = add.copy();
                int i;
                while(true) {
                    i = copy.getCount();
                    copy.setCount(storePartialItemStack(inv, copy));
                    if(copy.isEmpty() || copy.getCount() >= i) {
                        break;
                    }
                }
                return copy.getCount();
            }
        }
    }

    private static int storePartialItemStack(IInventory inv, ItemStack add) {
        int i = add.getCount();
        int j = storeItemStack(inv, add);
        if(j == -1) {
            j = getFirstEmptyStack(inv);
        }
        if(j == -1) {
            return i;
        }
        ItemStack stack = inv.getStackInSlot(j);
        if(stack.isEmpty()) {
            stack = add.copy();
            stack.setCount(0);
            if(add.hasTag()) {
                stack.setTag(add.getTag().copy());
            }
            inv.setInventorySlotContents(j, stack);
        }

        int k = i;
        if(i > stack.getMaxStackSize() - stack.getCount()) {
            k = stack.getMaxStackSize() - stack.getCount();
        }
        if(k > inv.getInventoryStackLimit() - stack.getCount()) {
            k = inv.getInventoryStackLimit() - stack.getCount();
        }

        if(k == 0) {
            return i;
        } else {
            i -= k;
            stack.grow(k);
            stack.setAnimationsToGo(5);
            return i;
        }
    }

    private static int storeItemStack(IInventory inv, ItemStack add) {
        for(int i = 0; i < inv.getSizeInventory(); i++) {
            if(canMergeStacks(inv, inv.getStackInSlot(i), add)) {
                return i;
            }
        }
        return -1;
    }

    private static boolean canMergeStacks(IInventory inv, ItemStack first, ItemStack sec) {
        return !first.isEmpty() && stackEqualExact(first, sec) && first.isStackable() && first.getCount() < first.getMaxStackSize() && first.getCount() < inv.getInventoryStackLimit();
    }

    public static boolean stackEqualExact(ItemStack first, ItemStack sec) {
        return first.getItem() == sec.getItem() && ItemStack.areItemStackTagsEqual(first, sec);
    }

    public static int getFirstEmptyStack(IInventory inv) {
        for(int i = 0; i < inv.getSizeInventory(); i++) {
            if(inv.getStackInSlot(i).isEmpty()) {
                return i;
            }
        }
        return -1;
    }
}
