// Copyright 2025, Algoryx Simulation AB.

#pragma once

// AGX Dynamics for Unreal includes.
#include "Terrain/TerrainParticleTypes.h"
#include "Terrain/AGX_Terrain.h"

// Unreal Engine includes.
#include "Components/ActorComponent.h"
#include "CoreMinimal.h"
#include "CoreTypes.h"
#include "NiagaraComponent.h"

#include "AGX_SoilParticleRendererComponent.generated.h"


/**
 * AGX SoilParticleRendererComponent is a component that enables real-time visualization 
 * of AGX Terrain soil particles within Unreal Engine using a Niagara particle system. 
 * This component comes with a default Niagara system that renders the particle data 
 * directly but it can be changed to a custom niagara system for customized particle 
 * rendering.
 *
 * The Niagara System can declare specific user parameters to enable the component
 * to populate them with specific particle data from the AGX Terrain. Because of
 * this, this component must be a child of an AGX Terrain actor, otherwise it will
 * not be able to fetch the particle data and supply it to the Niagara System.
 */
UCLASS(
	ClassGroup = "AGX_Terrain_Particle_Rendering", Blueprintable,
	meta = (BlueprintSpawnableComponent, ShortToolTip = "Component for rendering the particles produced by AGX_Terrain."))
class AGXUNREAL_API UAGX_SoilParticleRendererComponent : public UActorComponent
{
	GENERATED_BODY()

public:

	UAGX_SoilParticleRendererComponent();

	/** 
	 * Whether soil particles should be rendered or not. 
	 */
	UPROPERTY(EditAnywhere, Category = "AGX Soil Particle Rendering")
	bool bEnableParticleRendering = true;

	/**
	 * The Niagara VFX System that will be used to visualize the particles
	 * generated by the AGX Terrain. This component will provide values to 
	 * the Niagara system if the corresponding inputs are declared as user
	 * parameters within the system (see the default PS_SoilParticleSystem).
	 * 
	 * Available Input:
	 * 
	 * - Array Float 4:	Positions And Radii
	 * - Array Float 4:	Orientations
	 * - Array Float 4:	Velocities And Masses
	 * - Array Bool:	Exists
	 * - int32:			Particle Count
	 */
	UPROPERTY(EditAnywhere, Category = "AGX Soil Particle Rendering")
	UNiagaraSystem* ParticleSystemAsset;

	UFUNCTION(BlueprintCallable, Category = "AGX Soil Particle Rendering")
	void SetEnableParticleRendering(bool bEnabled);

	UFUNCTION(BlueprintCallable, Category = "AGX Soil Particle Rendering")
	bool GetEnableParticleRendering() const;

	UFUNCTION(BlueprintCallable, Category = "AGX Soil Particle Rendering")
	UNiagaraComponent* GetParticleSystemComponent();

	const UNiagaraComponent* GetParticleSystemComponent() const;

protected:

	// ~Begin ActorComponent interface
	virtual void BeginPlay() override;
	// ~End ActorComponent interface
	
	// ~Begin UObject interface.
#if WITH_EDITOR
	virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& Event) override;
	virtual void PostInitProperties() override;
#endif
	// ~End UObject interface.

private:

	UNiagaraComponent* ParticleSystemComponent = nullptr;

	UFUNCTION()
	void HandleParticleData(FDelegateParticleData& data);

#if WITH_EDITOR
	void InitPropertyDispatcher();
#endif
};
