#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "DBDTunableRowHandle.h"
#include "TunableStat.h"
#include "Templates/SubclassOf.h"
#include "K29SurvivorStatus.h"
#include "K29PowerStatusHandlerComponent.generated.h"

class UCurveFloat;
class UStatusEffect;
class UK29SurvivorThrowableComponent;
class UChargeableInteractionDefinition;
class ASurvivor;

UCLASS(Blueprintable, EditInlineNew, meta=(BlueprintSpawnableComponent))
class THEK29_API UK29PowerStatusHandlerComponent : public UActorComponent
{
	GENERATED_BODY()

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _maxInfectionLevel;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _infectionAddedPerTickWhileActive;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UCurveFloat* _stabilizingHealAmountByUsage;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _initialInfectionLevel;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _addedInfectionLevelsOnGrab;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _infectionHealingMultiplier;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _infectionIncubationThreshold;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _useInfectionRemoverChargeTime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<UStatusEffect> _hinderedStatusEffectClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<UStatusEffect> _gateBlockerStatusEffectClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<UK29SurvivorThrowableComponent> _survivorThrowableClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<UChargeableInteractionDefinition> _useInfectionRemoverInteractionSelfClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<UChargeableInteractionDefinition> _useInfectionRemoverInteractionOtherClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int32 _maxInfectionLevelWhenHooked;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float _recentlyGrabbedThresholdSeconds;

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_SurvivorStatusList, meta=(AllowPrivateAccess=true))
	TArray<FK29SurvivorStatus> _survivorStatusList;

private:
	UFUNCTION(BlueprintCallable, Server, Reliable)
	void Server_ReleaseSurvivor(ASurvivor* survivor, bool isForced);

	UFUNCTION(BlueprintCallable, Server, Reliable)
	void Server_GrabSurvivor(ASurvivor* survivor, const bool isProcessingInitialInfection);

	UFUNCTION(BlueprintCallable)
	void OnRep_SurvivorStatusList(TArray<FK29SurvivorStatus> oldSurvivorStatus);

	UFUNCTION(BlueprintCallable)
	void OnIntroCompleted();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_UseStabilizingSpray(ASurvivor* targetSurvivor);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_RemoveSurvivorFromLocker(ASurvivor* survivor);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_ReleaseSurvivor(ASurvivor* survivor, bool isForced);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_GrabSurvivor(ASurvivor* survivor, const bool isProcessingInitialInfection);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_DropSurvivor(ASurvivor* leftSurvivor);

	UFUNCTION(BlueprintCallable)
	bool IsInfectionIncreasingForSurvivor(const ASurvivor* survivor);

public:
	UFUNCTION(BlueprintPure)
	int32 GetMaxInfectionLevelWhenHooked() const;

	UFUNCTION(BlueprintCallable)
	int32 GetMaxInfectionLevel();

	UFUNCTION(BlueprintCallable)
	int32 GetInfectionLevel(const ASurvivor* survivor);

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnGrabbingNonInfectedSurvivor();

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnGrabbingInfectedSurvivor();

public:
	UFUNCTION(BlueprintCallable)
	void Authority_UseStabilizingSpray(ASurvivor* instigatingSurvivor, ASurvivor* targetSurvivor);

	UFUNCTION(BlueprintCallable, Exec)
	void Authority_SetAllSurvivorsToMaxInfection();

	UFUNCTION(BlueprintCallable, Exec)
	void Authority_SetAllSurvivorsToInitialInfection();

private:
	UFUNCTION(BlueprintCallable)
	void Authority_OnSurvivorImmoblizedChanged();

	UFUNCTION(BlueprintCallable)
	void Authority_OnSurvivorAdded(ASurvivor* survivor);

public:
	UFUNCTION(BlueprintCallable)
	void Authority_OnSlash(ASurvivor* targetSurvivor);

	UFUNCTION(BlueprintCallable)
	void Authority_HealInfectionLevels(const ASurvivor* survivor, const int32 infectionLevelsToHeal, const bool shouldSetInfectionActiveToFalse);

	UFUNCTION(BlueprintCallable, Exec)
	void Authority_HealAllSurvivorsInfectionWithStabilizingSpray();

	UFUNCTION(BlueprintCallable)
	void Authority_AddInfectionLevels(const ASurvivor* survivor, const int32 infectionToAdd);

	UFUNCTION(BlueprintCallable)
	void AddToTimesCuredByHeal(const ASurvivor* survivor);

public:
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

public:
	UK29PowerStatusHandlerComponent();
};

FORCEINLINE uint32 GetTypeHash(const UK29PowerStatusHandlerComponent) { return 0; }
