// Copyright 2026, Algoryx Simulation AB.

#pragma once

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

// Unreal Engine includes.
#include "Components/SceneComponent.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", Blueprintable, meta = (BlueprintSpawnableComponent))
class AGXUNREAL_API UAGX_SoilParticleRendererComponent : public USceneComponent
{
	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
};
