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


#include "NPCAIController.h"

#include "NavigationSystem.h"
#include "NPCTargetLocation.h"
#include "AI/NavigationSystemBase.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Perception/AISense_Sight.h"
#include "NakedDesire/Global/NakedDesireGameMode.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
#include "NakedDesire/Stats/StatsManager.h"
#include "Perception/AIPerceptionComponent.h"

void ANPCAIController::SetShouldReactToPlayer(const bool Value)
{
	Blackboard->SetValueAsBool(FName(TEXT("ShouldReactToPlayer")), Value);
}

void ANPCAIController::OnPossess(APawn* InPawn)
{
	Super::OnPossess(InPawn);

	NavigationSystem = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
	GameMode = Cast<ANakedDesireGameMode>(UGameplayStatics::GetGameMode(GetWorld()));

	RunBehaviorTree(BehaviorTreeAsset);

	const FVector SpawnLocation = InPawn->GetActorLocation();

	TArray<AActor*> TargetActors;
	UGameplayStatics::GetAllActorsOfClass(GetWorld(), ANPCTargetLocation::StaticClass(), TargetActors);

	const int RandomIndex = FMath::RandRange(0, TargetActors.Num() - 1);
	Blackboard->SetValueAsVector("TargetLocation", TargetActors[RandomIndex]->GetActorLocation());
	Blackboard->SetValueAsVector("SpawnLocation", SpawnLocation);

	PlayerCharacter = Cast<ANakedDesireCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
	Blackboard->SetValueAsObject("Player", PlayerCharacter);
	
	PerceptionComponent->OnTargetPerceptionUpdated.AddUniqueDynamic(this, &ANPCAIController::OnTargetPerceptionUpdate);
}

void ANPCAIController::OnUnPossess()
{
	if (bCurrentlyObserving && PlayerCharacter)
	{
		PlayerCharacter->StatsManager->SetObserved(false);
		bCurrentlyObserving = false;
	}
	Super::OnUnPossess();
}

void ANPCAIController::OnTargetPerceptionUpdate(AActor* Actor, FAIStimulus Stimulus)
{
	if (Actor != PlayerCharacter)
		return;
	if (Stimulus.Type != UAISense::GetSenseID<UAISense_Sight>())
		return;

	const bool bSensed = Stimulus.WasSuccessfullySensed();
	if (bSensed == bCurrentlyObserving)
		return;

	bCurrentlyObserving = bSensed;
	PlayerCharacter->StatsManager->SetObserved(bSensed);
}
