// Project Sword & Gun Copyright © 2021 Kevin Poretti

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "SwordNGun/SNGTypes.h"

#include "SNGEventBlueprintLibrary.generated.h"

/**
 *	Helpers functions for getting different data structs from a SNGEvent
 *
 *	In each event is a union of different SNGEventData structs. These structs can be of various sizes and can have different
 *	memory layouts. Because of the nature of unions in C++, the union will be the size of the largest member within it.
 *	This means we can have a flat array or container of SNGEvent structs even if the events are of different "types".
 *
 *	Blueprints cannot access the members of a union directly (can't use UPROPERTY on a union) even if the member itself is
 *	specified as a BlueprintType. This class returns the specific member of the EventData union within a SNGEvent struct
 *	so that it can be read by Blueprints.
 *
 *	If you are adding a new SNGEventData type to the union and want it accessible from Blueprints you will need to add a
 *	getter function to this class.
 */
UCLASS()
class SWORDNGUN_API USNGEventBlueprintLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	/**
	 *	Returns the CommandData member of the SNGEventData union
	 *
	 *	@param Event the event you want to get a specific SNGEventData from
	 *	@returns CommandData member of the SNGEventData union 
	 */
	UFUNCTION(BlueprintCallable)
	// NOTE(kevin): parameter should probably be a reference
	// I remember not making this a reference because this would make the blueprint node treat Event as a return value
	// instead of an input value. I feel there is a way to have Event appear in blueprints as an input value even though
	// it is a reference in the underlying C++ code. Need to investigate...
	static FSNGCharacterCommandData GetEventDataAsCommandData(const FSNGEvent Event);

	/**
	 *	Returns the DamageData member of the SNGEventData union
	 *
	 *	@param Event the event you want to get a specific SNGEventData from
	 *	@returns DamageData member of the SNGEventData union 
	 */
	UFUNCTION(BlueprintCallable)
	// NOTE(kevin): parameter should probably be a reference
	// I remember not making this a reference because this would make the blueprint node treat Event as a return value
	// instead of an input value. I feel there is a way to have Event appear in blueprints as an input value even though
	// it is a reference in the underlying C++ code. Need to investigate...
	static FSNGDamageData GetEventDataAsDamageData(const FSNGEvent Event);
};
