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

#pragma once

#include "CoreMinimal.h"
#include "Serialization/JsonReader.h"
#include "Serialization/JsonSerializer.h"
#include "JsonObjectConverter.h"
#include "Kismet/BlueprintFunctionLibrary.h"

#include "InworldCommandTypes.generated.h"

/**
 * @struct FInworldCommandResponse
 * @brief Contains data from LLM call that extracts potential command information from the player's input. 
 */
USTRUCT(BlueprintType)
struct INWORLDCOMMAND_API FInworldCommandResponse
{
	GENERATED_BODY()

	/** The command identifier the LLM believes the player is triggering (i.e., for "Hide behind the bush" it would be "Hide") */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|Command")
	FName Command;

	/** The subject of the command (i.e., for "Hide behind the bush" it would be "bush") */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|Command")
	FName Subject;

	/** Describes how the command should be executed (i.e., for "Hide behind the bush" it would be "behind") */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld|Command")
	FName Adverb;
};

UCLASS()
class INWORLDCOMMAND_API UInworldCommandJsonHelper : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:

	/**
	 * @brief Takes a string containing JSON and deserializes it into a command response
	 * @param JsonString The string containing valid JSON
	 * @return Command response structure
	 */
	UFUNCTION(BlueprintCallable, Category = "Inworld|Command")
	static FInworldCommandResponse ParseJsonToCommandResponse(const FString& JsonString)
	{
		FString JsonStringCopy = JsonString.Replace(TEXT("```json\n"), TEXT(""));
		JsonStringCopy = JsonStringCopy.Replace(TEXT("\n```"), TEXT(""));
		
		FInworldCommandResponse Response;
        
		TSharedPtr<FJsonObject> JsonObject;
		TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonStringCopy);
        
		if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
		{
			FString CommandString = JsonObject->GetStringField(TEXT("Command"));
			FString SubjectString = JsonObject->GetStringField(TEXT("Subject"));
			FString AdverbString = JsonObject->GetStringField(TEXT("Adverb"));
            
			Response.Command = FName(*CommandString);
			Response.Subject = FName(*SubjectString);
			Response.Adverb = FName(*AdverbString);
		}
		return Response;
	}
};
