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

#include "Graph/Nodes/InworldNode_GetRuntimeData.h"

FInworldDataHandle UInworldNode_GetRuntimeData::Process_GetRuntimeData(UInworldProcessContext* ProcessContext)
{
	if (ProcessContext == nullptr)
	{
		return FInworldData_Error("Invalid Process Context!");
	}

	if (FInworldDataHandle DataHandle; ProcessContext->GetRuntimeData(RuntimeDataKey, DataHandle) && DataHandle.IsValid())
	{
		UStruct* DataStruct = DataHandle->GetScriptStruct();
		if (FInworldData_Struct* Struct = DataHandle.Unwrap<FInworldData_Struct>())
		{
			DataStruct = Struct->GetDataScriptStruct();
			if (FInworldData_Object Object; Struct->GetData(Object))
			{
				DataStruct = Object.Object != nullptr ? Object.Object->GetClass() : nullptr;
			}
		}
		switch (DataType)
		{
			case EInworldGetRuntimeDataType::STRUCT:
				if (DataStruct != StructType)
				{
					return FInworldData_Error(
						FString::Format(TEXT("Failed to match RuntimeData for Key {0}. Expected Struct {1}, but found {2} instead"),
							{RuntimeDataKey.ToString(), StructType != nullptr ? StructType->GetName() : TEXT("nullptr"),
								DataStruct != nullptr ? DataStruct->GetName() : TEXT("nullptr")}));
				}
				break;
			case EInworldGetRuntimeDataType::OBJECT:
				if (DataStruct != *ObjectType)
				{
					return FInworldData_Error(
						FString::Format(TEXT("Failed to match RuntimeData for Key {0}. Expected Class {1}, but found {2} instead"),
							{RuntimeDataKey.ToString(), *ObjectType != nullptr ? *ObjectType->GetName() : TEXT("nullptr"),
								DataStruct != nullptr ? DataStruct->GetName() : TEXT("nullptr")}));
				}
				break;
			case EInworldGetRuntimeDataType::BOOL:
				if (DataStruct != FInworldData_Bool::StaticStruct())
				{
					return FInworldData_Error(
						FString::Format(TEXT("Failed to match RuntimeData for Key {0}. Expected Bool, but found {1} instead"),
							{RuntimeDataKey.ToString(), DataStruct != nullptr ? DataStruct->GetName() : TEXT("nullptr")}));
				}
				break;
			case EInworldGetRuntimeDataType::INT:
				if (DataStruct != FInworldData_Int::StaticStruct())
				{
					return FInworldData_Error(
						FString::Format(TEXT("Failed to match RuntimeData for Key {0}. Expected Int, but found {1} instead"),
							{RuntimeDataKey.ToString(), DataStruct != nullptr ? DataStruct->GetName() : TEXT("nullptr")}));
				}
				break;
			case EInworldGetRuntimeDataType::FLOAT:
				if (DataStruct != FInworldData_Float::StaticStruct())
				{
					return FInworldData_Error(
						FString::Format(TEXT("Failed to match RuntimeData for Key {0}. Expected Float, but found {1} instead"),
							{RuntimeDataKey.ToString(), DataStruct != nullptr ? DataStruct->GetName() : TEXT("nullptr")}));
				}
				break;
			default:
				checkNoEntry();
				break;
		}
		return DataHandle;
	}
	else
	{
		return FInworldData_Error(FString::Format(TEXT("No runtime data found for key: {0}"), {RuntimeDataKey.ToString()}));
	}
}
