/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */

#include "Graph/RuntimeData/InworldGraphRuntimeData_Goals.h"

#include "Graph/InworldGraph.h"
#include "InworldCharacterTypes.h"

UInworldGraphRuntimeData_Goals::UInworldGraphRuntimeData_Goals()
{
	Key = "Goals";
}

FInworldDataHandle UInworldGraphRuntimeData_Goals::GetData()
{
	FInworldGoalsData GoalsData;
	GoalsData.GoalsMap = GoalsMap;
	GoalsData.GoalParameterInterface = TScriptInterface<IInworldGoalParameterInterface>(ParameterSourceObject.Get());
	return FInworldData_Struct(GoalsData);
}

void UInworldGraphRuntimeData_Goals::Set(UDataTable* InGoalTable)
{
	GoalTable = InGoalTable;
	GoalsMap = {};
	if (IsValid(GoalTable))
	{
		TArray<const FInworldGoal*> GoalEntries;
		for (FName Name : GoalTable->GetRowNames())
		{
			if (FInworldGoal* Goal = GoalTable->FindRow<FInworldGoal>(Name, FString(TEXT("UInworldGraphRuntimeData_Goals::Set")));
				Goal != nullptr)
			{
				GoalsMap.Add(Name, *Goal);
			}
		}
	}
}

void UInworldGraphRuntimeData_Goals::Initialize_Implementation()
{
	Set(GoalTable);
	Super::Initialize_Implementation();
}

bool UInworldGraphRuntimeData_Goals::TryGetGoal(FName GoalName, FInworldGoal& GoalOut) const
{
	if (GoalsMap.Contains(GoalName))
	{
		GoalOut = GoalsMap.FindRef(GoalName);
		return true;
	}
	return false;
}

bool UInworldGraphRuntimeData_Goals::TryGetGoalFromIntent(FName IntentName, FInworldGoal& GoalOut) const
{
	for (const auto& GoalPair : GoalsMap)
	{
		const FInworldGoal& Goal = GoalPair.Value;
		if (Goal.Intents.Contains(IntentName))
		{
			GoalOut = Goal;
			return true;
		}
	}
	return false;
}

void UInworldGraphRuntimeData_Goals::CompleteGoal(FName GoalName)
{
	if (GoalsMap.Contains(GoalName) && !GoalsMap[GoalName].bRepeatable)
	{
		GoalsMap.Remove(GoalName);
	}
	UE_LOG(LogInworldGraph, Log, TEXT("Completed goal: %s"), *GoalName.ToString());
}

void UInworldGraphRuntimeData_Goals::AddGoal(FName GoalName, const FInworldGoal& Goal)
{
	if (!GoalsMap.Contains(GoalName))
	{
		GoalsMap.Add(GoalName, Goal);
	}
}

void UInworldGraphRuntimeData_Goals::RemoveGoal(FName GoalName)
{
	if (GoalsMap.Contains(GoalName))
	{
		GoalsMap.Remove(GoalName);
	}
}

void UInworldGraphRuntimeData_Goals::ClearAllGoals()
{
	GoalsMap.Empty();
}

void UInworldGraphRuntimeData_Goals::SetParameterSourceObject(UObject* Source)
{
	if (IsValid(Source))
	{
		if (Source->Implements<UInworldGoalParameterInterface>())
		{
			ParameterSourceObject = Source;
		}
		else
		{
			UE_LOG(LogInworldGraph, Error,
				TEXT("Attempted to register '%s' as parameter source object "
					 "but it doesn't implement IInworldGoalParameterInterface"),
				*Source->GetName());
		}
	}
}

IInworldGoalParameterInterface* UInworldGraphRuntimeData_Goals::GetParameterSourceObject() const
{
	return Cast<IInworldGoalParameterInterface>(ParameterSourceObject.Get());
}

TArray<FName> UInworldGraphRuntimeData_Goals::GetGoalsMapKeys() const
{
	TArray<FName> KeysArray;
	GoalsMap.GenerateKeyArray(KeysArray);
	return KeysArray;
}
