//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
///			Copyright 2019 (C) Bruno Xavier B. Leite
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "PoolSpawnOptions.h"
#include "Runtime/Engine/Classes/Components/SplineComponent.h"
#include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h"

#include "PooledSplineProjectile.generated.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class UObjectPool;
class APooledPawn;
class APooledActor;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOBJP_ProjectileHit, const FHitResult&, ImpactResult);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Pooled Spline Projectile

///  Pooled Spline Projectile Template;
/// This Projectile Component works better with bullet Actors that are generated by an Object-Pool Component.
UCLASS(ClassGroup="Synaptech", Category="Movement", meta=(BlueprintSpawnableComponent, DisplayName="Pool Spline Projectile", ShortTooltip="Pooled Spline Projectile Class."))
class OBJPOOL_API UPooledSplineProjectile : public UActorComponent {
	GENERATED_BODY()
	//
	UPooledSplineProjectile();
	//
	friend class APooledActor;
	friend class APooledPawn;
	friend class UObjectPool;
protected:
	FHitResult HitResult;
	float PathDistance;
	//
	UPROPERTY() APooledPawn* POwner;
	UPROPERTY() APooledActor* AOwner;
	UPROPERTY() UPrimitiveComponent* Primitive;
	UPROPERTY() USplineComponent* SplineComponent;
public:
	virtual void PostInitProperties() override;
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
	//
	//
	UPROPERTY(Category="Projectile", EditAnywhere, BlueprintReadWrite)
	float PathWidth;
	//
	UPROPERTY(Category="Projectile", EditAnywhere, BlueprintReadWrite)
	float Speed;
	//
	UPROPERTY(Category="Projectile", EditAnywhere, BlueprintReadWrite)
	TArray<TEnumAsByte<EObjectTypeQuery>>PathCollisionQueryTypes;
	//
	UPROPERTY(Category="Projectile", EditAnywhere, BlueprintReadWrite)
	TArray<AActor*>IgnoredActorsOnCollisionQuery;
	//
	UPROPERTY(Category="Projectile", EditAnywhere, BlueprintReadWrite)
	TEnumAsByte<EDrawDebugTrace::Type>CollisionQueryDebugMode;
	//
	//
	/// Event called every time this Projectile hits something.
	UPROPERTY(Category="Projectile", BlueprintAssignable)
	FOBJP_ProjectileHit OnProjectileHit;
	//
	//
	/// Returns reference to the Spline Component used as track path.
	UFUNCTION(Category = "Projectile", BlueprintCallable, meta = (DisplayName="Get Projectile Spline Component", Keywords="get projectile spline"))
	USplineComponent* GetSplineComponent() const;
	//
	/// Defines reference to the target Spline Component used as track path.
	UFUNCTION(Category = "Projectile", BlueprintCallable, meta = (DisplayName="Set Spline Component", Keywords="get projectile spline"))
	void SetSplineComponent(USplineComponent* Target);
	//
	/// Manually fire this Projectile, instead of relying on Component Initialization.
	UFUNCTION(Category = "Projectile", BlueprintNativeEvent, meta = (DisplayName="Shoot", Keywords="shoot projectile"))
	void Shoot(); virtual void Shoot_Implementation();
	//
	/// Manually stops this Projectile, instead of relying on Component Destruction.
	UFUNCTION(Category = "Projectile", BlueprintNativeEvent, meta = (DisplayName="Break", Keywords="break projectile"))
	void Break(); virtual void Break_Implementation();
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////