#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Templates/SubclassOf.h"
#include "DBDTunableRowHandle.h"
#include "GameplayTagContainer.h"
#include "EHealthState.h"
#include "UObject/NoExportTypes.h"
#include "Engine/HitResult.h"
#include "SnowballPlayerComponent.generated.h"

class UTimerObject;
class USnowballProvider;
class USnowballProjectileLauncher;
class UInteractionDefinition;
class ADBDPlayer;

UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
class WINTEREVENT2023_API USnowballPlayerComponent : public UActorComponent
{
	GENERATED_BODY()

private:
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_CooldownTimer, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UTimerObject* _cooldownTimer;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<USnowballProvider> _snowballProviderClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<USnowballProjectileLauncher> _snowballLauncherClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<UInteractionDefinition> _snowballThrowingInteractionClassSurvivor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<UInteractionDefinition> _snowballThrowingInteractionClassKiller;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<UInteractionDefinition> _proximityInteractionClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FDBDTunableRowHandle _cooldownDuration;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FGameplayTagContainer _hideVignetteVFXTags;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FGameplayTagContainer _hidePlayerVFXTags;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_SnowballThrowInteraction, Instanced, meta=(AllowPrivateAccess=true))
	UInteractionDefinition* _snowballThrowInteraction;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	int32 _projectilePreviewPointAmount;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FDBDTunableRowHandle _snowballCarryLimit;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FDBDTunableRowHandle _snowballNeededForEmpoweredSnowball;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FDBDTunableRowHandle _snowballNeededForEmpoweredSnowballWithOffering;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_SnowballProvider, Transient, Instanced, meta=(AllowPrivateAccess=true))
	USnowballProvider* _snowballProvider;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_SnowballLauncher, Transient, Instanced, meta=(AllowPrivateAccess=true))
	USnowballProjectileLauncher* _snowballLauncher;

private:
	UFUNCTION(BlueprintCallable)
	void OnRep_SnowballThrowInteraction();

	UFUNCTION(BlueprintCallable)
	void OnRep_SnowballProvider();

	UFUNCTION(BlueprintCallable)
	void OnRep_SnowballLauncher();

	UFUNCTION(BlueprintCallable)
	void OnRep_CooldownTimer();

	UFUNCTION(BlueprintCallable)
	void OnOwningCamperGuidedStateChanged();

	UFUNCTION(BlueprintCallable)
	void OnCamperDamageStateChanged(EHealthState oldDamageState, EHealthState newDamageState);

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

	UFUNCTION(BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_ShowSnowballTrajectoryPreview(const TArray<FVector>& points, float currentChargePercent, float arcLengthAtImpactPoint, const FHitResult& hitResult, bool isHittingValidTarget);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnVFXVignetteTagAddedOrRemoved(ADBDPlayer* player, bool added);

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnSnowballsDepleted(ADBDPlayer* owningPlayer);

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnPlayerVFXTagAddedOrRemoved(ADBDPlayer* player, bool added);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnPlayerUnhidden(ADBDPlayer* owningPlayer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnPlayerHidden(ADBDPlayer* owningPlayer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnPlayerDiedOrBeingKilled(ADBDPlayer* deadPlayer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnLocallyObservedChanged(bool isLocallyObserved, ADBDPlayer* owningPlayer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnChargePercentChanged(float chargePercent);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnCamperPickUpEndOrDropped(ADBDPlayer* pickedUpPlayer);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnCamperPickedUp(ADBDPlayer* pickedUpPlayer);

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

public:
	USnowballPlayerComponent();
};

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