#pragma once

#include "CoreMinimal.h"
#include "KillerAbilityComponent.h"
#include "TunableStat.h"
#include "DBDTunableRowHandle.h"
#include "GameplayTagContainer.h"
#include "GameEventData.h"
#include "K35KillerTeleportPointSpawningManager.generated.h"

class UCurveFloat;
class AKiller;
class AK35KillerTeleportPoint;

UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
class UK35KillerTeleportPointSpawningManager : public UKillerAbilityComponent
{
	GENERATED_BODY()

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _maximumChargeTime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _chargeTimerReductionMultiplierOnManuallyDestroyingKillerTeleportPoint;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _spawnTime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _spawnTimeReductionOnSurvivorHookedWithKillerTeleportPointNearby;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _spawnTimeReductionOnInjuredSurvivorWithKillerEffect;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _addon16SpawnTimeReductionOnWallOrPalletBreakPercentage;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTunableStat _spawnTimeReductionOnAfflictedSurvivorWithKillerEffect;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UCurveFloat* _spawnTimeMultiplierBySurvivorsAffectedWithKillerEffectCurve;

private:
	UFUNCTION()
	void OnSurvivorInjuredWithKillerEffect(FGameplayTag gameEventType, const FGameEventData& gameEventData);

	UFUNCTION()
	void OnSurvivorAfflictedWithKillerEffect(FGameplayTag gameEventType, const FGameEventData& gameEventData);

	UFUNCTION()
	void OnKillerManuallyDestroyedKillerTeleportPoint(FGameplayTag gameEventType, const FGameEventData& gameEventData);

	UFUNCTION(BlueprintCallable)
	void OnKillerAdded(AKiller* killer);

	UFUNCTION(BlueprintCallable)
	void OnIntroCompleted();

	UFUNCTION()
	void OnGeneratorFixed(FGameplayTag gameEventType, const FGameEventData& gameEventData);

	UFUNCTION()
	void OnBreakWallOrPallet(FGameplayTag gameEventType, const FGameEventData& gameEventData);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnSpawningStarted();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnSpawningComplete(AK35KillerTeleportPoint* acquiredTeleportPoint);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnSpawningCancelled();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnHookCausedRecycle();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnChargingStarted();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnChargingComplete();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_CompleteChargingTime();

public:
	UFUNCTION(BlueprintPure)
	bool IsSpawnTimerActive() const;

	UFUNCTION(BlueprintPure)
	bool IsChargeTimerActive() const;

	UFUNCTION(BlueprintPure)
	bool IsAbleToSpawnKillerTeleportPoint() const;

	UFUNCTION(BlueprintPure)
	float GetSpawnTimerProgress() const;

	UFUNCTION(BlueprintPure)
	float GetChargeTimerProgress() const;

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnSpawningStarted(const AKiller* killer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnSpawningCancelled(const AKiller* killer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnSpawnComplete(const AKiller* killer, const AK35KillerTeleportPoint* acquiredTeleportPoint);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnChargingStarted(const AKiller* killer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnChargingComplete(const AKiller* killer, const bool isSpawningPossible);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnChargeTimerReduced(const AKiller* killer);

private:
	UFUNCTION()
	void Authority_OnSurvivorHookedChanged(FGameplayTag gameEventType, const FGameEventData& gameEventData);

	UFUNCTION(BlueprintCallable)
	void Authority_OnSpawnTimerEnded();

public:
	UK35KillerTeleportPointSpawningManager();
};

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