#pragma once

#include "CoreMinimal.h"
#include "KillerControls.h"
#include "DBDPlayer.h"
#include "UObject/NoExportTypes.h"
#include "Templates/SubclassOf.h"
#include "EKillerAbilities.h"
#include "TargetFocusTimer.h"
#include "DBDTimer.h"
#include "AnimationMontageDescriptor.h"
#include "TagStateBool.h"
#include "GameplayTagContainer.h"
#include "EAttackType.h"
#include "EAttackZoneSet.h"
#include "EKillerCarryAnimWeight.h"
#include "EStunType.h"
#include "Killer.generated.h"

class ASurvivorExposerInstance;
class UKillerSoundCuesComponent;
class UAkComponent;
class UDBDNavModifierComponent;
class UKillerBloodFXComponent;
class ULoudNoiseHUDIndicator;
class UKillerHitsWhileCarryingTrackerComponent;
class ASurvivor;
class UMoriComponent;
class UFinisherMoriHandlerComponent;
class UHitValidatorComponent;
class UHitValidatorConfigurator;
class UDBDAttackerComponent;
class UArmIKSensorComponent;
class UFirstPersonViewComponent;
class UKillerIntroComponent;
class UKillerBlindingFXComponent;
class UKillerRedStainUpdateStrategy;
class USceneComponent;
class UKillerStunnableComponent;
class AActor;
class UKillerMovementComponent;
class UChaserCharacterComponent;

UCLASS(Blueprintable)
class DEADBYDAYLIGHT_API AKiller : public ADBDPlayer, public IKillerControls
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnStalkModeChangedEvent, bool, isInStalkMode);

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool _setFirstPersonModeEnabledOnKillerIntroCompleted;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FVector PutDownTraceLocation;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FName DefaultSlasherPower;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float LoudNoiseDisplayTime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FVector TargetPriorityFactor;

	UPROPERTY(BlueprintReadWrite, Transient)
	bool ShouldDisplayAttackZones;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<ASurvivorExposerInstance> CamperExposer;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TArray<EKillerAbilities> KillerAbilities;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced)
	UKillerSoundCuesComponent* KillerSoundCuesComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool ShowKillerPowerDebugInfo;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FOnStalkModeChangedEvent OnStalkModeChangedEvent;

protected:
	UPROPERTY(EditAnywhere, Export)
	TWeakObjectPtr<UAkComponent> _audioComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UDBDNavModifierComponent* _terrorNavModifierComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UKillerBloodFXComponent* _bloodFXComponent;

	UPROPERTY(BlueprintReadWrite, Transient)
	float _slasherLightIntensity;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float _defaultAmountToSquish;

	UPROPERTY(BlueprintReadWrite, Transient)
	TMap<ADBDPlayer*, FTargetFocusTimer> _stalkTimers;

	UPROPERTY(BlueprintReadWrite, Transient)
	FDBDTimer _recentlyCloakedTimer;

	UPROPERTY(BlueprintReadWrite, Transient)
	FDBDTimer _flashlightBlindEvasionScoreTimer;

	UPROPERTY(BlueprintReadWrite, Transient)
	FDBDTimer _flashlightBurnoutEvasionScoreTimer;

	UPROPERTY(BlueprintReadWrite, Transient)
	TMap<ADBDPlayer*, FAnimationMontageDescriptor> _predictedCamperHitMontages;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FName CameraSocketName;

private:
	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	ULoudNoiseHUDIndicator* _loudNoiseIndicator;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UKillerHitsWhileCarryingTrackerComponent* _hitsWhileCarryingTracker;

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	float _stealthIncreaseRate;

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	float _stealthDecreaseRate;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, meta=(AllowPrivateAccess=true))
	FTagStateBool _isInStalkMode;

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

	UPROPERTY(Replicated, Transient)
	int8 _allowedKillCount;

	UPROPERTY(Replicated, Transient)
	int8 _allowedKillAfterStrugglePhase;

	UPROPERTY(BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	int32 _cachedBloodlustTier;

	UPROPERTY(Replicated, Transient)
	uint32 _killerPowerDebugFlags;

	UPROPERTY(EditAnywhere)
	FGameplayTag _presenceTag;

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

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

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

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	ASurvivor* _carriedSurvivor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UMoriComponent* _moriComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UFinisherMoriHandlerComponent* _finisherMoriHandlerComponent;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UHitValidatorComponent* _hitValidator;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UHitValidatorConfigurator* _hitValidationConfigurator;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UDBDAttackerComponent* _attackerComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	EAttackType _basicAttackType;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UArmIKSensorComponent* _armIKSensorComponent;

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	ASurvivor* _survivorBeingKilled;

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	TSubclassOf<UFirstPersonViewComponent> _firstPersonViewComponentClass;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UFirstPersonViewComponent* _firstPersonViewComponent;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UKillerIntroComponent* _killerIntroComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UKillerBlindingFXComponent* _blindingFXComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UKillerRedStainUpdateStrategy* _redStainUpdateStrategy;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FName _squishFactorParameter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	USceneComponent* _attackZonePivot;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UKillerStunnableComponent* _slasherStunnableComponent;

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

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void UpdateRageTierEffect(int32 previousTier, int32 currentTier);

protected:
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void SpawnSlasherPower();

public:
	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	bool ShouldApplyBloodlustSpeedModifier() const;

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

	UFUNCTION(BlueprintCallable)
	void SetStalkTierWalkSpeedMultiplier(float stalkTierWalkSpeedMultiplier);

	UFUNCTION(BlueprintCallable)
	void SetLightIntensity(float intensity);

	UFUNCTION(BlueprintCallable)
	void SetIsKilling(bool isKilling);

	UFUNCTION(BlueprintCallable)
	void SetIsHookingSurvivor(const bool value);

protected:
	UFUNCTION(BlueprintCallable)
	void SetIsCloaked(bool isCloaked, bool forced);

public:
	UFUNCTION(BlueprintCallable)
	void SetCarriedSurvivor(ASurvivor* survivor);

	UFUNCTION(BlueprintCallable)
	void SetAttackZonePivot(USceneComponent* attackZonePivot);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void SetAttackDetectionZoneSet(EAttackZoneSet attackZoneSet);

	UFUNCTION(BlueprintCallable, Server, Reliable)
	void Server_SendAttackInput(bool pressed);

	UFUNCTION(BlueprintCallable, Server, Reliable)
	void Server_SendActionKillerInput(bool pressed);

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void OnSurvivorHit(ASurvivor* survivor);

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void OnStealthChanged(bool stealth);

public:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void OnStalkModeChangedCosmetic(bool stalkMode);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void OnPerformingChargableInteraction(float Progress);

private:
	UFUNCTION(BlueprintCallable)
	void OnLoudNoiseTriggered(AActor* originator, AActor* instigatingActor, FVector location, bool shouldTrack, float& audibleRange, bool isQuickAction, bool isDeceivingNoise);

	UFUNCTION(BlueprintCallable)
	void OnLoudNoiseIndicatorDestroyed();

public:
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void OnKillerAbilityEndDeactivate(EKillerAbilities killerAbility, bool forced);

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void OnKillerAbilityEndActivate(EKillerAbilities killerAbility);

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void OnKillerAbilityBeginDeactivate(EKillerAbilities killerAbility, bool forced);

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void OnKillerAbilityBeginActivate(EKillerAbilities killerAbility);

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void OnIsKillingSurvivorWithMoriUpdated(bool isKillingSurvivorWithMori);

private:
	UFUNCTION(BlueprintCallable)
	void OnAttackStart(const EAttackType attackType);

	UFUNCTION(BlueprintCallable)
	void OnAttackFinish(const EAttackType attackType);

public:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_MergeLockOnDamageZones(bool enable);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_DisplayAttackZones(bool display);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_Cheat_SetAttackDetectionZoneSet(EAttackZoneSet attackZoneSet);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void MergeLockOnDamageZones(bool enable);

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	bool Local_CancelAttack();

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	bool IsUncloaking() const;

	UFUNCTION(BlueprintPure)
	bool IsStunned() const;

	UFUNCTION(BlueprintPure)
	bool IsKilling() const;

	UFUNCTION(BlueprintPure)
	bool IsInterruptBlocked() const;

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	bool IsImmuneToObservingPlayerDetection(const ADBDPlayer* observingPlayer) const;

	UFUNCTION(BlueprintCallable)
	bool IsIdling();

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	bool IsCrouchAvailable_BP();

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	bool IsCloaking() const;

	UFUNCTION(BlueprintPure)
	bool IsCarrying() const;

	UFUNCTION(BlueprintPure)
	bool IsAllowedToKill(const ASurvivor* survivor) const;

	UFUNCTION(BlueprintCallable)
	void IncrementInterruptBlock();

	UFUNCTION(BlueprintPure)
	bool HasPreLevelGenerationModifier(FName modifierID) const;

	UFUNCTION(BlueprintPure)
	bool HasKillerAbility(EKillerAbilities killerAbility) const;

	UFUNCTION(BlueprintPure)
	ASurvivor* GetSurvivorBeingKilled() const;

	UFUNCTION(BlueprintPure)
	float GetStealthRatio() const;

	UFUNCTION(BlueprintPure)
	float GetStalkTierWalkSpeedMultiplier() const;

	UFUNCTION(BlueprintPure)
	int32 GetRageTier() const;

	UFUNCTION(BlueprintPure)
	FGameplayTag GetPresenceTag() const;

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	FVector GetPlayerDropOffPoint() const;

	UFUNCTION(BlueprintPure)
	ASurvivor* GetObsessionTarget() const;

	UFUNCTION(BlueprintPure)
	FRotator GetLookRotation() const;

	UFUNCTION(BlueprintPure)
	float GetLightIntensity() const;

	UFUNCTION(BlueprintPure)
	UKillerMovementComponent* GetKillerMovement() const;

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	EKillerCarryAnimWeight GetKillerCarryAnimWeight() const;

	UFUNCTION(BlueprintPure)
	bool GetIsAttacking() const;

	UFUNCTION(BlueprintCallable)
	float GetCurrentRotationYaw();

	UFUNCTION(BlueprintPure)
	UChaserCharacterComponent* GetChaserCharacterComponent() const;

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	TArray<FName> GetCharacterCustomAnimTags() const;

public:
	UFUNCTION(BlueprintPure)
	ASurvivor* GetCarriedSurvivor() const;

	UFUNCTION(BlueprintPure)
	float GetBlindedPercent() const;

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	USceneComponent* GetAttackZonePivot();

	UFUNCTION(BlueprintPure)
	float GetAnimDirection() const;

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void DisplayAttackZones(bool display);

	UFUNCTION(BlueprintCallable)
	void DecrementInterruptBlock();

	UFUNCTION(BlueprintCallable, Exec)
	void DBD_SetAttackZones(EAttackZoneSet attackZoneSet);

	UFUNCTION(BlueprintCallable, Exec)
	void DBD_MergeLockOnDamageZones(bool enable);

	UFUNCTION(BlueprintCallable, Exec)
	void DBD_DisplayAttackZones(bool display);

	UFUNCTION(BlueprintCallable, Exec)
	void DBD_AllowKilling();

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

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

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

	UFUNCTION(BlueprintCallable, Client, Reliable)
	void Client_RequestStun(EStunType stunType, ADBDPlayer* stunner, float stunQueueTime);

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	bool CanSlashAttack_BP() const;

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	bool CanPerformKillerAbility(EKillerAbilities killerAbility) const;

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	bool CanGainRage() const;

	UFUNCTION(BlueprintCallable)
	bool CancelAttackByInput();

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	bool CanAttack_BP(const EAttackType attackType) const;

	UFUNCTION(BlueprintPure)
	bool CanAttack(const EAttackType attackType) const;

	UFUNCTION(BlueprintPure)
	bool CanAffectLocalPlayer() const;

	UFUNCTION(BlueprintCallable)
	void BroadcastOnInstantTeleport();

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	void Authority_SetInStalkMode(bool stalkMode, bool forced);

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	void Authority_RequestStun(EStunType stunType, ADBDPlayer* requester, float stunQueueTime);

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	void Authority_AllowKilling(int32 numKills);

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

public:
	AKiller();
};

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