#include "LatentWaiter.h"

FImplementableLatentAction::FImplementableLatentAction(UWorld* world_, const FLatentActionInfo& LatentInfo)
	: Latenter(world_->SpawnActor<ALatenterActor>())
	, ExecutionFunction(LatentInfo.ExecutionFunction)
	, OutputLink(LatentInfo.Linkage)
	, CallbackTarget(LatentInfo.CallbackTarget)
{
}

// Latentノードを終了させるかどうか、毎フレーム実行される関数
void FImplementableLatentAction::UpdateOperation(FLatentResponse& Response)
{
	Response.FinishAndTriggerIf(!(Latenter->IsValidLowLevel() && !Latenter->IsActorBeingDestroyed()), ExecutionFunction, OutputLink, CallbackTarget);
}


ALatenterActor::ALatenterActor()
{
	PrimaryActorTick.bCanEverTick = false;
	SetActorHiddenInGame(true);
}

void ALatenterActor::FinishWait()
{
	Destroy();
}


void UBPFL_Latenter::WaitUntilFinished(const UObject* worldContextObject_, FLatentActionInfo latentInfo_, const FWaitUntilFinishedDispatcher onEventDispatcher)
{
	if (UWorld* world = GEngine->GetWorldFromContextObject(worldContextObject_))
	{
		FLatentActionManager& lam = world->GetLatentActionManager();
		if (lam.FindExistingAction<FImplementableLatentAction>(latentInfo_.CallbackTarget, latentInfo_.UUID) == nullptr)
		{
			FImplementableLatentAction* action = new FImplementableLatentAction(world, latentInfo_);
			lam.AddNewAction(latentInfo_.CallbackTarget, latentInfo_.UUID, action);

			onEventDispatcher.ExecuteIfBound(action->Latenter);
		}
	}
}