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


#include "InventoryComponent.h"
#include "Items/BaseItem.h"


// Sets default values for this component's properties
UInventoryComponent::UInventoryComponent()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;
	
	static ConstructorHelpers::FClassFinder<UUserWidget> InventoryNotificationWidgetClassFinder(TEXT("/Game/Blueprints/Status_UI/InventoryNotification"));
	InventoryNotificationWidgetClass = InventoryNotificationWidgetClassFinder.Class;

	MaxItemSlots = 10;
}


// Called when the game starts
void UInventoryComponent::BeginPlay()
{
	Super::BeginPlay();

	InventoryNotificationWidgetInstance = CreateWidget<UUserWidget>(GetWorld(), InventoryNotificationWidgetClass);
	InventoryNotificationWidgetInstance->AddToViewport(20);

	//activates the AddItem function for every DefaultItem that inherits BaseItem
	for (auto& BaseItem : DefaultItems)
	{
		AddItem(BaseItem);
	}
}

bool UInventoryComponent::AddItem(class UBaseItem* BaseItem)
{
	//if the items is over the maxinventoryslots then it wont add the item
	if (Items.Num() >= MaxItemSlots || !BaseItem)
	{
		UE_LOG(LogTemp, Display, TEXT("THERE ARE MORE ITEMS THAN THE INVENTORY SLOTS"));
		return false;
	}
	BaseItem->StoredItems = this;
	BaseItem->World = GetWorld();
	bool isNewItem = true;
	for (auto& Item : Items)
	{
		//if the item is the same as the item that is being added
		if (Item->ItemDisplayName.ToString() == BaseItem->ItemDisplayName.ToString())
		{
			Item->StackCount += BaseItem->StackCount;
			OnItemAdd.Broadcast(BaseItem->ItemDisplayName.ToString(), BaseItem->StackCount);
			UE_LOG(LogTemp, Display, TEXT("ITEM STACKCOUNT: %d"), Item->StackCount);
			isNewItem = false;
			break;
		}
	}
	if (isNewItem == true)
	{
		Items.Add(BaseItem);
		OnItemAdd.Broadcast(BaseItem->ItemDisplayName.ToString(), BaseItem->StackCount);
		UE_LOG(LogTemp, Display, TEXT("ITEM HAS BEEN ADDED TO INVENTORY"));
	}
	//Refreshes the inventory
	OnInventoryUpdated.Broadcast();
	return true;
}

// remove only gets called once on the same item
bool UInventoryComponent::Remove(class UBaseItem* BaseItem)
{
	if (BaseItem)
	{
		UE_LOG(LogTemp, Display, TEXT("ItEM HAS BEEN REMOVED"));
		BaseItem->StoredItems = nullptr;
		BaseItem->World = nullptr;
		Items.RemoveSingle(BaseItem);
		OnInventoryUpdated.Broadcast(); // Updates UI
		return true;
	}
	return false;
}

UBaseItem* UInventoryComponent::GetItem(int Index)
{
	return Items[Index];
}

void UInventoryComponent::RemoveItem(UEatableItems* Item)
{
	Item->StackCount--;
	if (Item->StackCount <= 0)
	{
		Remove(Item); // activates the remove function up above
	}
	OnInventoryUpdated.Broadcast();
}

int UInventoryComponent::GetItemAmount(const int& ItemID)
{
	if (Items.Num() > 0)
	{
		for (UBaseItem* const& Item : Items)
		{
			if (Item->ItemID == ItemID)
			{
				return Item->StackCount;
			}
		}
	}
	return -1;
}

void UInventoryComponent::RemoveItemID(const int& ItemID)
{
	if (Items.Num() > 0)
	{
		for (UBaseItem* const& Item : Items)
		{
			if (Item->ItemID == ItemID)
			{
				RemoveItem(Cast<UEatableItems>(Item));
			}
		}
	}
}

UBaseItem* UInventoryComponent::GetItemByID(const int& ItemID)
{
	if (Items.Num() > 0)
	{
		for (UBaseItem* const& Item : Items)
		{
			if (Item->ItemID == ItemID)
			{
				return Item;
			}
		}
	}
	return nullptr;
}