#pragma once

#include "CoreMinimal.h"
#include "GameflowEventsNotifier.h"
#include "GameFramework/GameState.h"
#include "EscapeDoorActivatedEvent.h"
#include "EIntroState.h"
#include "OnKillerIntroCompletePercentChanged.h"
#include "LightingGeneratedEvent.h"
#include "AllPlayerLoadedEvent.h"
#include "SlasherSetEvent.h"
#include "ObsessionChangedDynamicDelegate.h"
#include "EServerUseNetAsyncLoading.h"
#include "BuiltLevelData.h"
#include "OfferingData.h"
#include "UObject/NoExportTypes.h"
#include "GamePresetData.h"
#include "EEndGameReason.h"
#include "EventTrackerObjectiveLevelEntry.h"
#include "SelectedOffering.h"
#include "UObject/SoftObjectPtr.h"
#include "OnSlasherSetDelegate.h"
#include "EGameState.h"
#include "DBDGameState.generated.h"

class USpecialEventGameplaySpawnerComponent;
class USpecialBehaviourGameplaySpawnerComponent;
class AKiller;
class URenderingFeaturesSequencer;
class AClipManager;
class AFadeManager;
class ASurvivor;
class UEndGameStateComponent;
class UScourgeHookManagerComponent;
class UActorPairQueryEvaluatorComponent;
class ULoudNoiseEventSystem;
class UHudStateComponent;
class UBackendGameplayTunablesComponent;
class UCharacterCollection;
class UCollectableCollection;
class UServerTimeProviderComponent;
class UInGameAssetPreloaderComponent;
class UOnScreenDebugComponent;
class UBhvrBlackboardComponent;
class UObject;
class ADBDPlayerState_Menu;
class AActor;
class ADBDPlayer;
class ADBDPlayerState;
class APawn;
class UAkAudioBank;

UCLASS(Blueprintable)
class DEADBYDAYLIGHT_API ADBDGameState : public AGameState, public IGameflowEventsNotifier
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_DELEGATE(FOnLevelReadyToPlayDelegate);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnKillerSetMultiDelegate, AKiller*, killer);

	DECLARE_DYNAMIC_DELEGATE(FOnIntroCompleteDelegate);

public:
	UPROPERTY(BlueprintReadWrite, BlueprintAssignable, Transient)
	FEscapeDoorActivatedEvent OnEscapeDoorActivated;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient)
	EIntroState IntroState;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FOnKillerIntroCompletePercentChanged OnKillerIntroCompletePercentChanged;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FLightingGeneratedEvent OnLightingGenerated;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, Instanced)
	USpecialEventGameplaySpawnerComponent* _specialEventGameplaySpawnerComponent;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, Instanced)
	USpecialBehaviourGameplaySpawnerComponent* _specialBehaviourGameplaySpawnerComponent;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FAllPlayerLoadedEvent AuthorityOnAllPlayerLoaded;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FSlasherSetEvent OnSlasherSet;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FObsessionChangedDynamicDelegate OnObsessionChanged;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_SecondsLeftInLobby, Transient)
	int32 SecondsLeftInLobby;

protected:
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient)
	AKiller* Slasher;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient)
	URenderingFeaturesSequencer* _renderingSequencer;

private:
	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_UseNetAsyncLoading, Transient, meta=(AllowPrivateAccess=true))
	EServerUseNetAsyncLoading _useNetAsyncLoading;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_GameLevelLoadingStarted, Transient, meta=(AllowPrivateAccess=true))
	bool _gameLevelLoadingStarted;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_BuildLevelData, Transient, meta=(AllowPrivateAccess=true))
	FBuiltLevelData _builtLevelData;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	FOfferingData _levelOfferings;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	AClipManager* _clipManager;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	AFadeManager* _fadeManager;

	UPROPERTY(EditInstanceOnly, ReplicatedUsing=OnRep_SessionId, Transient)
	FGuid _sessionId;

	UPROPERTY(EditInstanceOnly, ReplicatedUsing=OnRep_LobbyId, Transient)
	FGuid _lobbyId;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_EscapeDoorActivated, Transient, meta=(AllowPrivateAccess=true))
	bool _escapeDoorActivated;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	bool _levelReadyToPlay;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	bool _playerDistributionReady;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	bool _usingWeakenedMechanic;

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

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_ObsessionTarget, Transient, meta=(AllowPrivateAccess=true))
	ASurvivor* _obsessionTarget;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	bool _cachedObsessionEscaped;

	UPROPERTY(EditInstanceOnly, ReplicatedUsing=OnRep_NumberOfSurvivorsKilledOrSacrificed, Transient)
	int8 _numberOfSurvivorsKilledOrSacrificed;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_GamePresetData, Transient, meta=(AllowPrivateAccess=true))
	FGamePresetData _gamePresetData;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_OnGameLevelCreated, Transient, meta=(AllowPrivateAccess=true))
	bool _gameLevelCreated;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	bool _gameLevelEnded;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	bool _gameTimedOut;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	EEndGameReason _gameEndedReason;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	bool _isLoadoutFrozen;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UEndGameStateComponent* _endGameState;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UScourgeHookManagerComponent* _scourgeHookManager;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UActorPairQueryEvaluatorComponent* _actorPairQueryEvaluatorComponent;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	ULoudNoiseEventSystem* _loudNoiseEventSystem;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UHudStateComponent* _hudStateComponent;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UBackendGameplayTunablesComponent* _backendGameplayTunablesComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UCharacterCollection* _characterCollection;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UCollectableCollection* _collectableCollection;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UServerTimeProviderComponent* _serverTimeProvider;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UInGameAssetPreloaderComponent* _inGameAssetPreloaderComponent;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UOnScreenDebugComponent* _onScreenDebugComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UBhvrBlackboardComponent* _blackboardComponent;

	UPROPERTY(EditInstanceOnly, Replicated, Transient)
	FDateTime _matchStartTime;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	bool _isServerDedicated;

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

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	FString _serverBuildVersion;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	FString _serverContentVersion;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	FString _serverSessionId;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	FString _serverRegion;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	FString _serverMatchId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	float _introDuration;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	bool _leaveSpectateRequested;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	TArray<FEventTrackerObjectiveLevelEntry> _eventTrackerObjectiveLevels;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	bool _isForPreview;

private:
	UFUNCTION(BlueprintCallable)
	void UpdateMatchOpenForMorePlayer(bool isOpen) const;

public:
	UFUNCTION(BlueprintCallable)
	void UnsetLevelReadyToPlay();

	UFUNCTION(BlueprintCallable)
	void UnregisterFromIntroCompleteAndLevelReadyToPlay(const UObject* inObject);

	UFUNCTION(BlueprintCallable)
	void SortOfferings();

	UFUNCTION(BlueprintCallable)
	void SetPlayersReadyToStart(bool playersReadyToStart);

	UFUNCTION(BlueprintCallable)
	void SetLevelReadyToPlay();

	UFUNCTION(BlueprintCallable)
	void SetKillerIntroCompletedNormalized(float completedAmount);

	UFUNCTION(BlueprintCallable)
	void SetGameLevelEnded(EEndGameReason endGameReason);

	UFUNCTION(BlueprintCallable)
	void SetDisplayMapName(bool display);

	UFUNCTION(BlueprintCallable)
	void Server_UpdateGameRole();

	UFUNCTION(BlueprintCallable)
	void ResetGameLevelStatus();

private:
	UFUNCTION(BlueprintCallable)
	void OnRep_UseNetAsyncLoading();

	UFUNCTION(BlueprintCallable)
	void OnRep_SessionId();

	UFUNCTION(BlueprintCallable)
	void OnRep_SecondsLeftInLobby(const int32 oldValue);

	UFUNCTION(BlueprintCallable)
	void OnRep_OnGameLevelCreated();

	UFUNCTION(BlueprintCallable)
	void OnRep_ObsessionTarget(ASurvivor* previousObsessionTarget);

	UFUNCTION(BlueprintCallable)
	void OnRep_NumberOfSurvivorsKilledOrSacrificed();

	UFUNCTION(BlueprintCallable)
	void OnRep_LobbyId();

	UFUNCTION(BlueprintCallable)
	void OnRep_GamePresetData();

	UFUNCTION(BlueprintCallable)
	void OnRep_GameLevelLoadingStarted(bool oldValue);

	UFUNCTION(BlueprintCallable)
	void OnRep_EscapeDoorActivated(bool oldValue);

	UFUNCTION(BlueprintCallable)
	void OnRep_BuildLevelData();

	UFUNCTION(BlueprintCallable)
	void OnLevelReadyToPlay();

public:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_UpdateCharacterFromGamePreset(ADBDPlayerState_Menu* playerState_Menu, const FGamePresetData& gamePresetData);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SetServerLeftGame(bool hasServerLeftGame);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SetLostServerConnection(bool hasLostServerConnection);

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

private:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SetGameLevelEnded(EEndGameReason endGameReason);

public:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SetGameEnded(bool hasServerLeftGame);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SetBuiltLevelData(const FBuiltLevelData& builtLevelData);

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

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SendHVSPlusState(bool enabled);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SendEnsureToClients(const FString& ensure);

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

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_FireLoudNoiseNotification(AActor* loudNoiseInstigator, const FVector& location, bool shouldTrack, float audibleRange, ADBDPlayer* instigatingPlayer, bool isQuickAction, bool isDeceivingNoise);

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

	UFUNCTION(BlueprintPure)
	bool IsPlayerDistributionReady() const;

	UFUNCTION(BlueprintPure)
	bool IsOnePlayerLeft() const;

	UFUNCTION(BlueprintCallable)
	bool IsOfferingReceived() const;

	UFUNCTION(BlueprintCallable)
	bool IsObsessionTargetAliveInLevel();

	UFUNCTION(BlueprintCallable)
	bool IsObsessionTargetAlive();

	UFUNCTION(BlueprintPure)
	bool IsLightingGenerated() const;

	UFUNCTION(BlueprintPure)
	bool IsLevelReadyToPlay() const;

	UFUNCTION(BlueprintPure)
	bool IsIntroCompleted() const;

	UFUNCTION(BlueprintPure)
	bool IsEscapeDoorActivated() const;

	UFUNCTION(BlueprintCallable)
	void IntroCompleted();

	UFUNCTION(BlueprintPure)
	USpecialEventGameplaySpawnerComponent* GetSpecialEventGameplaySpawnerComponent() const;

	UFUNCTION(BlueprintCallable)
	TArray<FSelectedOffering> GetSelectedOfferings() const;

	UFUNCTION(BlueprintCallable)
	bool GetSelectedOffering(int32 index, FSelectedOffering& selectedOffering) const;

	UFUNCTION(BlueprintCallable)
	ADBDPlayerState* GetPlayerStateByMirrorsID(const FString& id) const;

	UFUNCTION(BlueprintCallable)
	ADBDPlayerState* GetPlayerStateByIDString(const FString& playerHexEncodedUniqueId, bool isReplacementBot) const;

	UFUNCTION(BlueprintPure)
	bool GetPlayersReadyToStart() const;

	UFUNCTION(BlueprintPure)
	void GetPlayerRoleCounts(int32& survivorCount, int32& killerCount, int32& spectatorCount) const;

	UFUNCTION(BlueprintPure)
	ASurvivor* GetObsessionTarget() const;

	UFUNCTION(BlueprintPure)
	int32 GetNumberOfOtherActiveSurvivors(ADBDPlayer* exception) const;

	UFUNCTION(BlueprintPure)
	int32 GetNumberOfActiveSurvivors() const;

	UFUNCTION(BlueprintPure)
	FName GetMapThemeName() const;

	UFUNCTION(BlueprintPure)
	ADBDPlayer* GetLocalPlayerPawn() const;

	UFUNCTION(BlueprintPure)
	APawn* GetLocalPlayerBasePawn() const;

	UFUNCTION(BlueprintCallable)
	TSoftObjectPtr<UAkAudioBank> GetLevelThemeAudioSoundBankAssetPtr() const;

	UFUNCTION(BlueprintCallable)
	FBuiltLevelData GetLevelData() const;

	UFUNCTION(BlueprintPure)
	float GetKillerIntroCompletedNormalized() const;

	UFUNCTION(BlueprintPure)
	AKiller* GetKiller() const;

	UFUNCTION(BlueprintPure)
	bool GetIsGameEnded() const;

	UFUNCTION(BlueprintPure)
	bool GetGameLevelLoadingStarted() const;

	UFUNCTION(BlueprintPure)
	UEndGameStateComponent* GetEndGameStateComponent() const;

	UFUNCTION(BlueprintPure)
	UCollectableCollection* GetCollectableCollection() const;

	UFUNCTION(BlueprintPure)
	UCharacterCollection* GetCharacterCollection() const;

	UFUNCTION(BlueprintCallable)
	void CallOnSlasherSet(FOnSlasherSetDelegate callback);

	UFUNCTION(BlueprintCallable)
	void CallOnLevelReadyToPlay(FOnLevelReadyToPlayDelegate callback);

	UFUNCTION(BlueprintCallable)
	void CallOnIntroComplete(FOnIntroCompleteDelegate callback);

	UFUNCTION(BlueprintCallable)
	void BroadcastOnSetBuildLevelData();

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	void Authority_UpdateHatchState();

	UFUNCTION(BlueprintCallable)
	void Authority_SignalEscapeDoorActivated(bool newEscapeDoorActivated);

	UFUNCTION(BlueprintCallable)
	void Authority_SetObsessionTarget(ASurvivor* obsessionTarget);

	UFUNCTION(BlueprintCallable)
	void Authority_SetGameStarted();

	UFUNCTION(BlueprintCallable)
	void Authority_SetGameSelectedOffering(const TArray<FSelectedOffering>& offerings);

	UFUNCTION(BlueprintCallable)
	void Authority_SetGameLevelEnded(EEndGameReason endGameReason);

	UFUNCTION(BlueprintCallable)
	void Authority_SetGameLevelCreated();

	UFUNCTION(BlueprintCallable)
	void Authority_SetBuiltLevelData(const FBuiltLevelData& builtLevelData);

	UFUNCTION(BlueprintCallable)
	void Authority_SetAllPlayerLoaded();

private:
	UFUNCTION(BlueprintCallable)
	void Authority_OnPlayerGameStateChangedAddIfKilled(ADBDPlayerState* playerState, EGameState gameState);

public:
	UFUNCTION(BlueprintCallable)
	void Authority_OnGameLevelLoaded();

	UFUNCTION(BlueprintCallable)
	void Authority_EvaluateObsessionTarget(ADBDPlayer* potentialTarget);

	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly)
	void Authority_EscapeThroughHatch();

	UFUNCTION(BlueprintCallable)
	void Authority_EnableObsession();

	UFUNCTION(BlueprintCallable)
	void Authority_DeactivateAI();

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

public:
	ADBDGameState();
};

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