#pragma once

#include "CoreMinimal.h"
#include "KillerDependentObjectInterface.h"
#include "BaseTrap.h"
#include "OnIsTrapSetChanged.h"
#include "Templates/SubclassOf.h"
#include "GameplayTagContainer.h"
#include "TunableStat.h"
#include "Engine/HitResult.h"
#include "BearTrap.generated.h"

class UBoxPlayerOverlapComponent;
class UCapsulePlayerOverlapComponent;
class UBoxComponent;
class UDBDOutlineComponent;
class UBearTrapOutlineUpdateStrategy;
class UMapActorComponent;
class USphereComponent;
class UMontagePlayer;
class ADBDPlayer;
class UStatusEffect;
class UDBDNavModifierComponent;
class UInteractor;
class UInteractionDefinition;
class UAnimationMontageSlave;
class ADBDPlayerState;
class UAnimMontage;
class UPrimitiveComponent;
class AActor;
class UBearTrapAnimInstance;
class UAkComponent;
class ASurvivor;

UCLASS(Blueprintable)
class ABearTrap : public ABaseTrap, public IKillerDependentObjectInterface
{
	GENERATED_BODY()

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UBoxPlayerOverlapComponent* _interactionVolume;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UCapsulePlayerOverlapComponent* _trapPlayerDetectionZone;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UBoxComponent* _killerSafetyZoneComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UDBDOutlineComponent* _outlineComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UBearTrapOutlineUpdateStrategy* _outlineUpdateStrategy;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UMapActorComponent* _mapActorComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	USphereComponent* _mapActorCollision;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	USphereComponent* _trapBlocker;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UMontagePlayer* _montagePlayer;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FOnIsTrapSetChanged _onIsTrapSetChanged;

	UPROPERTY(BlueprintReadWrite, Transient)
	ADBDPlayer* _ownerPlayer;

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

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UDBDNavModifierComponent* _dangerNavModifierComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	bool _isTrapperOutOfSafetyZone;

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

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

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

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UInteractor* _mainInteractor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UInteractionDefinition* _trapSurvivor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UInteractionDefinition* _trapKiller;

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	ADBDPlayer* _trappedPlayer;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UAnimationMontageSlave* _animationMontageSlave;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FTunableStat _baseBearTrapCarryCapacity;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UStatusEffect* _honingStoneStatusEffect;

	UPROPERTY(ReplicatedUsing=OnRep_OwningPlayerState, Transient)
	TWeakObjectPtr<ADBDPlayerState> _owningPlayerState;

public:
	UFUNCTION(BlueprintCallable)
	void TrySetTrappedPlayer(ADBDPlayer* player);

	UFUNCTION(BlueprintCallable)
	void SetTrappedPlayerSinceMoved(bool didTrap);

protected:
	UFUNCTION(BlueprintCallable)
	void SetTrappedPlayer(ADBDPlayer* trappedPlayer);

public:
	UFUNCTION(BlueprintPure=false, BlueprintCallable)
	void PlayMontage(UAnimMontage* montage) const;

private:
	UFUNCTION(BlueprintCallable)
	void OnTrappedPlayerPickedUp(ADBDPlayer* picker);

	UFUNCTION(BlueprintCallable)
	void OnTrappedInjuredBleedoutKO(ADBDPlayer* injuredBleedoutInstigator);

	UFUNCTION(BlueprintCallable)
	void OnTrapDetectionZoneOverlapEnd(UPrimitiveComponent* overlappedComponent, AActor* otherActor, UPrimitiveComponent* otherComp, int32 otherBodyIndex);

	UFUNCTION()
	void OnTrapDetectionZoneOverlapBegin(UPrimitiveComponent* overlappedComponent, AActor* otherActor, UPrimitiveComponent* otherComp, int32 otherBodyIndex, bool bFromSweep, const FHitResult& sweepResult);

	UFUNCTION(BlueprintCallable)
	void OnSafetyZoneEndOverlap(UPrimitiveComponent* overlappedComponent, AActor* otherActor, UPrimitiveComponent* otherComp, int32 otherBodyIndex);

	UFUNCTION(BlueprintCallable)
	void OnRep_OwningPlayerState();

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void OnPlayerTrapped(ADBDPlayer* trappedPlayer);

private:
	UFUNCTION(BlueprintCallable)
	void OnLevelReadyToPlay_Implementation();

	UFUNCTION(BlueprintCallable)
	void OnGuidedStateChanged();

	UFUNCTION(BlueprintCallable)
	void OnCollectUpdateStart();

	UFUNCTION(BlueprintCallable)
	void OnCollectUpdateEnd();

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

	UFUNCTION(BlueprintCallable)
	void InitializeTrapSurvivorInteraction(UInteractionDefinition* interaction);

	UFUNCTION(BlueprintCallable)
	void InitializeTrapKillerInteraction(UInteractionDefinition* interaction);

	UFUNCTION(BlueprintCallable)
	void InitializeMainInteractor(UInteractor* interactor);

	UFUNCTION(BlueprintPure)
	bool HasTrappedPlayerSinceMoved() const;

	UFUNCTION(BlueprintPure)
	bool HasTrappedPlayer() const;

	UFUNCTION(BlueprintPure)
	ADBDPlayer* GetTrappedPlayer() const;

	UFUNCTION(BlueprintPure)
	int32 GetSelfUntrapAttemptsRemaining() const;

	UFUNCTION(BlueprintPure)
	int32 GetMaximumAttemptsForSelfUntrap() const;

	UFUNCTION(BlueprintPure)
	UBearTrapAnimInstance* GetAnimInstance() const;

protected:
	UFUNCTION(BlueprintPure, BlueprintImplementableEvent)
	UAkComponent* GetAkAudioComponent() const;

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

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

public:
	ABearTrap();
};

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