#pragma once

#include "CoreMinimal.h"
#include "PoolableActor.h"
#include "GameFramework/Actor.h"
#include "UObject/NoExportTypes.h"
#include "AnimationMontageDescriptor.h"
#include "GameplayTagContainer.h"
#include "Templates/SubclassOf.h"
#include "DBDTunableRowHandle.h"
#include "FloatRotation_NetQuantize8.h"
#include "ECalamariCageCancelReason.h"
#include "CalamariCageEntity.generated.h"

class USceneComponent;
class UDBDSkeletalMeshComponentBudgeted;
class UMontagePlayer;
class ACalamariCage;
class ASurvivor;
class AKiller;
class UTimerObject;
class ADBDPlayer;

UCLASS(Blueprintable)
class CALAMARI_API ACalamariCageEntity : public AActor, public IPoolableActor
{
	GENERATED_BODY()

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	USceneComponent* _rootComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UDBDSkeletalMeshComponentBudgeted* _skeletalMeshComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FVector _offsetFromKillerToSpawnClaw;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FVector _offsetFromKillerToSpawnClawWhenPullingFromLocker;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FRotator _rotationOffset;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	UMontagePlayer* _montagePlayer;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FAnimationMontageDescriptor _inMontage;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FAnimationMontageDescriptor _outMontage;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FAnimationMontageDescriptor _hookSurvivorMontage;

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

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	FVector _survivorSnapOffset;

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

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

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

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TArray<TSubclassOf<AActor>> _portalSpawnActorClassesToIgnore;

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

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

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<ACalamariCage> _calamariCageClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TWeakObjectPtr<ASurvivor> _hookedSurvivor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TWeakObjectPtr<AKiller> _killerInstigator;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TWeakObjectPtr<ACalamariCage> _cage;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	TArray<AActor*> _portalSpawnIgnoreActors;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, ReplicatedUsing=OnRep_SendToCagePickupDelayTimer, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UTimerObject* _sendToCagePickupDelayTimerObject;

protected:
	UFUNCTION(BlueprintPure=false, BlueprintCallable)
	void SetEntityVisibility(bool isVisible) const;

private:
	UFUNCTION(BlueprintCallable)
	void OnRep_SendToCagePickupDelayTimer();

public:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SpawnEntity(ASurvivor* survivor, AKiller* killer, const float pickUpDuration, FVector spawnLocation, FFloatRotation_NetQuantize8 entityYaw);

private:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_NotifyStunWindowEnded(bool wasCancelled);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_CancelHook(ECalamariCageCancelReason reason);

public:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnSurvivorSentToCage(ASurvivor* cagedSurvivor);

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnEntitySpawned(FVector portalLocation);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnEntityHookCancelled(ASurvivor* survivor);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnEntityFinishedGoingUp(bool wasSentToCage);

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

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

public:
	ACalamariCageEntity();
};

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