// Project Sword & Gun Copyright © 2021 Kevin Poretti

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "SNGHealthComponent.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnHealthChangedSignature, USNGHealthComponent*, HealthComponent,
	float, Health, float, HealthDelta);

/**
 *	Manages the health of an actor. This component also manages aspects of health regeneration such as determining when
 *	health should start regenerating as well as the actual regeneration itself.
 */
UCLASS( ClassGroup=(SwordNGun), meta=(BlueprintSpawnableComponent) )
class SWORDNGUN_API USNGHealthComponent : public UActorComponent
{
	GENERATED_BODY()

public:	
	/** Sets default values for this component's properties */
	USNGHealthComponent();

	/**
	 *	Returns the current amount of health
	 *
	 *	@returns Current health
	 */ 
	UFUNCTION(BlueprintCallable)
	float GetHealth() const;

	/**
	 *	Adds health to the current health variable
	 *
	 *	@param Delta amount of health to add
	 */
	UFUNCTION(BlueprintCallable, Exec)
	void AddHealth(float Delta);

	/**
	 *	Subtracts health from the current health variable
	 *
	 *	@param Delta amount of health to add
	 */
	UFUNCTION (BlueprintCallable, Exec)
	void SubtractHealth(float Delta);
	
protected:
	/** Called when the game starts */
	virtual void BeginPlay() override;

	/** Current amount of health */
	UPROPERTY(BlueprintReadOnly)
	float Health;		

	/** Amount of health that can be recovered */
	UPROPERTY(BlueprintReadOnly)
	float RecoverableHealth;

	/** Amount of health that can be recovered */
	UPROPERTY(BlueprintReadOnly)
	float LastHealthSubtractionTime;
	
	/** Initial amount of health that will be set on BeginPlay */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health", meta = (ClampMin = 0.0f))
	float DefaultHealth;

	/** How fast health should regenerate once regeneration starts (in amount of health per second) */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health/Recovery", meta = (ClampMin = 0.0f))
	float RecoverSpeed;

	/** How often should health update once regeneration starts (in ticks per second) */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health/Recovery", meta = (ClampMin = 0.0f))
	float RecoverRate;
	
	/** The duration of time that must elapse since the last time health was subtracted for regeneration to start */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health/Recovery", meta = (ClampMin = 0.0f))
	float RecoverCooldownDuration;

	FTimerHandle TimerHandle_RecoverCooldown;

	FTimerHandle TimerHandle_RecoverTick;

	/**
	 *	Adds health back to Health variable and subtracts from RecoverableHealth ever (RecoverRate ticks / second)
	 */
	UFUNCTION()
	void RecoverHealthTick();

	/**
	 *	Sets up the health recovery timer 
	 */
	UFUNCTION()
	void OnRecoverCooldownEnd();
	
public:
	/**
	 *	Triggered when health is either added or subtracted
	 */
	UPROPERTY(BlueprintAssignable, Category = "Events")
	FOnHealthChangedSignature OnHealthChanged;
};
