#pragma once

#include "CoreMinimal.h"
#include "AIInteractableTargetInterface.h"
#include "Interactable.h"
#include "Templates/SubclassOf.h"
#include "TunableStat.h"
#include "WakerObject.generated.h"

class UBoxComponent;
class UInteractor;
class UEscapeDreamInteraction;
class UTimerObject;
class ADBDPlayer;
class USkeletalMeshComponent;
class UPrimitiveComponent;

UCLASS(Blueprintable)
class THENIGHTMARE_API AWakerObject : public AInteractable, public IAIInteractableTargetInterface
{
	GENERATED_BODY()

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, NoClear, Export, meta=(AllowPrivateAccess=true))
	UBoxComponent* _wakerObjectInteractionZone;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, NoClear, Export, meta=(AllowPrivateAccess=true))
	UInteractor* _wakerObjectInteractor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<UEscapeDreamInteraction> _escapeDreamInteractionClass;

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_EscapeDreamInteraction, Export, meta=(AllowPrivateAccess=true))
	UEscapeDreamInteraction* _escapeDreamInteraction;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_CooldownTimer, Export, meta=(AllowPrivateAccess=true))
	UTimerObject* _cooldownTimer;

private:
	UFUNCTION(BlueprintCallable)
	void OnRep_EscapeDreamInteraction();

	UFUNCTION(BlueprintCallable)
	void OnRep_CooldownTimer();

	UFUNCTION(BlueprintCallable)
	void OnInteractionEntered(ADBDPlayer* player);

public:
	UFUNCTION(BlueprintPure, BlueprintImplementableEvent)
	USkeletalMeshComponent* GetMesh() const;

	UFUNCTION(BlueprintPure)
	bool GetIsInteracting() const;

	UFUNCTION(BlueprintPure, BlueprintNativeEvent)
	UPrimitiveComponent* GetInteractorPrimitiveComponent() const;

	UFUNCTION(BlueprintPure)
	float GetInteractionPercentComplete() const;

	UFUNCTION(BlueprintPure)
	bool GetChargeComplete() const;

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_UpdateVisibility(const ADBDPlayer* locallyObservedPlayer, bool isInDreamworld);

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

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

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_CooldownTimeElapsed(float timeElapsedPercent);

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

public:
	AWakerObject();
};

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