#include <Item/IInventory.hpp>
#include <Item/Item.hpp>

int IInventory::countItems(ItemStack &templStack)
{
    int count = 0;
    
    int i;
    for (i=0; i<getNumSlots(); i++)
    {
        ItemStack stack = getStackInSlot(i);
        if (!stack.isEmpty() && templStack.canMergeFrom(stack))
        {
            count += stack.getStackSize();
        }
    }

    return count;
}

void IInventory::insertStack(ItemStack &insertingStack)
{
    // First try to merge it all in.
    int i;
    for (i=0; i<getNumSlots(); i++)
    {
        if (insertingStack.isEmpty())
        {
            return;
        }

        ItemStack current = getStackInSlot(i);
        if (current.isEmpty())
        {
            continue;
        }
        
        current.insertFrom(insertingStack);
        setStackInSlot(i, current);
    }

    // If anything is remaining, put it an empty slot.
    if (insertingStack.isEmpty())
    {
        return;
    }

    for (i=0; i<getNumSlots(); i++)
    {
        ItemStack current = getStackInSlot(i);
        if (current.isEmpty() && isAllowedStackInSlot(i, insertingStack))
        {
            setStackInSlot(i, insertingStack);
            insertingStack = ItemStack();
            return;
        }
    }
}

bool IInventory::canInsertStack(ItemStack &candidateStack)
{
    if (candidateStack.isEmpty())
    {
        return true;
    }

    int leftToInsert = candidateStack.getStackSize();

    // First check if it can all be merged in.
    int i;
    for (i=0; i<getNumSlots(); i++)
    {
        if (leftToInsert == 0)
        {
            break;
        }

        ItemStack current = getStackInSlot(i);
        if (current.isEmpty())
        {
            // Found an empty slot, so return.
            return true;
        }
        
        leftToInsert -= std::min(leftToInsert, current.getMaxInsertableFrom(candidateStack));
    }

    return leftToInsert == 0;
}