// © 2025 Naked People Team. All Rights Reserved.


#include "LocationSubsystem.h"

#include "LocationData.h"

void ULocationSubsystem::EnterLocation(ULocationData* Location)
{
	if (!Location)
		return;

	int32& Count = ActiveCounts.FindOrAdd(Location);
	++Count;

	if (Count == 1)
	{
		RebuildActiveTags();
		OnLocationEntered.Broadcast(Location);
	}
}

void ULocationSubsystem::ExitLocation(ULocationData* Location)
{
	if (!Location)
		return;

	int32* Count = ActiveCounts.Find(Location);
	if (!Count)
		return;

	if (--(*Count) <= 0)
	{
		ActiveCounts.Remove(Location);
		RebuildActiveTags();
		OnLocationExited.Broadcast(Location);
	}
}

bool ULocationSubsystem::IsPlayerInLocation(FGameplayTag Query) const
{
	return Query.IsValid() && ActiveTags.HasTag(Query);
}

ULocationData* ULocationSubsystem::GetCurrentLocation() const
{
	ULocationData* Best = nullptr;
	int32 BestDepth = -1;

	for (const TPair<TObjectPtr<ULocationData>, int32>& Pair : ActiveCounts)
	{
		ULocationData* Location = Pair.Key;
		if (!Location || !Location->Tag.IsValid())
			continue;

		// More tag segments = more specific (Location.City.Beach beats Location.City).
		const int32 Depth = Location->Tag.GetGameplayTagParents().Num();
		if (Depth > BestDepth)
		{
			BestDepth = Depth;
			Best = Location;
		}
	}

	return Best;
}

void ULocationSubsystem::RebuildActiveTags()
{
	ActiveTags.Reset();
	for (const TPair<TObjectPtr<ULocationData>, int32>& Pair : ActiveCounts)
	{
		if (Pair.Key && Pair.Key->Tag.IsValid())
			ActiveTags.AddTag(Pair.Key->Tag);
	}
}