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


#include "LocationTrigger.h"

#include "Components/BoxComponent.h"
#include "LocationSubsystem.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
#include "TimerManager.h"


ALocationTrigger::ALocationTrigger()
{
	PrimaryActorTick.bCanEverTick = false;

	BoxTrigger = CreateDefaultSubobject<UBoxComponent>("Box Trigger");
	RootComponent = BoxTrigger;
}

ULocationData* ALocationTrigger::GetLocationData() const
{
	return LocationData;
}

void ALocationTrigger::BeginPlay()
{
	Super::BeginPlay();

	BoxTrigger->OnComponentBeginOverlap.AddDynamic(this, &ALocationTrigger::OnTriggerBeginOverlap);
	BoxTrigger->OnComponentEndOverlap.AddDynamic(this, &ALocationTrigger::OnTriggerEndOverlap);

	// Defer to next tick so the player pawn is spawned and positioned and physics overlaps
	// have been computed before we check whether it started out inside this volume.
	GetWorld()->GetTimerManager().SetTimerForNextTick(this, &ALocationTrigger::SeedInitialPlayerOverlap);
}

void ALocationTrigger::OnConstruction(const FTransform& Transform)
{
	Super::OnConstruction(Transform);
	
	BoxTrigger->SetBoxExtent(TriggerSize);
}

void ALocationTrigger::OnTriggerBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
                                             UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (!OtherActor || !OtherActor->IsA<ANakedDesireCharacter>())
		return;

	SetPlayerInside(true);
}

void ALocationTrigger::OnTriggerEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	if (!OtherActor || !OtherActor->IsA<ANakedDesireCharacter>())
		return;

	// Another of the player's components may still overlap the box (capsule vs. mesh); only
	// report the exit once the player has fully left, so we fire exactly one Exit per Enter.
	if (IsPlayerOverlapping())
		return;

	SetPlayerInside(false);
}

void ALocationTrigger::SeedInitialPlayerOverlap()
{
	if (IsPlayerOverlapping())
		SetPlayerInside(true);
}

void ALocationTrigger::SetPlayerInside(const bool bInside)
{
	if (bInside == bPlayerInside)
		return;

	bPlayerInside = bInside;

	if (ULocationSubsystem* Locations = GetWorld()->GetSubsystem<ULocationSubsystem>())
	{
		if (bInside)
			Locations->EnterLocation(LocationData);
		else
			Locations->ExitLocation(LocationData);
	}
}

bool ALocationTrigger::IsPlayerOverlapping() const
{
	TArray<AActor*> Overlapping;
	BoxTrigger->GetOverlappingActors(Overlapping, ANakedDesireCharacter::StaticClass());
	return Overlapping.Num() > 0;
}