// Fill out your copyright notice in the Description page of Project Settings.


#include "Inventory.h"
#include "Faye/Inventory/Item.h"
#include "Faye/Data/Filters/ItemFilters.h"

void UInventory::AddItem(UItem* InItem, int32 Stack)
{
	if (!InItem || Stack <= 0)
		return;
	
	if (FItemStack* ItemStack = GetItemStack_Internal(InItem))
	{
		ItemStack->Stack += Stack;
	}
	else
	{
		FItemStack ItemStackNew;
		ItemStackNew.Stack = Stack;
		ItemStackNew.ItemPtr = InItem;
		ItemStacks.Add(ItemStackNew);
	}
}

bool UInventory::RemoveItem(const UItem* InItem, int32 Stacks)
{
	for (int32 i = 0; i < ItemStacks.Num(); ++i)
	{
		if (ItemStacks[i].ItemPtr == InItem)
		{
			if (Stacks == -1)
			{
				ItemStacks.RemoveAt(i);
			}
			else
			{
				ItemStacks[i].Stack -= Stacks;
				if (ItemStacks[i].Stack <= 0)
				{
					ItemStacks.RemoveAt(i);
				}
			}
			return true;
		}
	}
	
	return false;
}

bool UInventory::GetItemStack(const UItem* Item, FItemStack& OutItemStack) const
{
	if (!Item)
		return false;
	
	for (const FItemStack& Stack : ItemStacks)
	{
		if (Stack.ItemPtr == Item)
		{
			OutItemStack = Stack;
			return true;
		}
	}
	
	return false;
}

TArray<UItem*> UInventory::FilterItems(UItemFilter* Filter) const
{
	TArray<UItem*> FilteredItems;
	for (const FItemStack Stack : ItemStacks)
	{
		if (Filter->Pass(Stack.ItemPtr))
			FilteredItems.Add(Stack.ItemPtr);
	}
	return FilteredItems;
}

int32 UInventory::CountStacksForItems(const TArray<UItem*>& Items) const
{
	int32 Count = 0;
	for (const UItem* Item : Items)
	{
		FItemStack Stack;
		if (GetItemStack(Item, Stack))
		{
			Count += Stack.Stack;
		}
	}
	return Count;
}

bool UInventory::ModifyGold(int32 Amount)
{
	if (Amount < 0 && FMath::Abs(Amount) > Gold)
	{
		return false;
	}
	
	Gold += Amount;
	OnGoldChanged.Broadcast(Amount, Gold);
	return true;
}

FItemStack* UInventory::GetItemStack_Internal(const UItem* Item)
{
	if (!Item)
		return nullptr;
	
	for (FItemStack& Stack : ItemStacks)
	{
		if (Stack.ItemPtr == Item)
		{
			return &Stack;
		}
	}
	
	return nullptr;
}
