#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "Engine/CollisionProfile.h"
#include "LookingAtData.h"
#include "Engine/HitResult.h"
#include "LookAtScriptedEventMapTriggerComponent.generated.h"

class UShapeComponent;
class UStaticMeshComponent;
class ADBDPlayer;
class UPrimitiveComponent;
class AActor;

UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
class DBDGAMEPLAY_API ULookAtScriptedEventMapTriggerComponent : public USceneComponent
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_MULTICAST_DELEGATE(FLookAtScriptedEventTriggerEvent);

public:
	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FLookAtScriptedEventTriggerEvent _cosmetic_firstPlayerEnterTriggerVolumeEvent;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FLookAtScriptedEventTriggerEvent _cosmetic_lastPlayerExitTriggerVolumeEvent;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FLookAtScriptedEventTriggerEvent _cosmetic_lookTowardPointEvent;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FLookAtScriptedEventTriggerEvent _cosmetic_noLookTowardPointEvent;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FLookAtScriptedEventTriggerEvent _cosmetic_eventTriggeredEvent;

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FCollisionProfileName _triggerVolumeCollisionProfile;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float _precisionAngleDegrees;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool _useLookAtTimer;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float _lookAtTimerTime;

private:
	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UShapeComponent* _playerTriggerVolume;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UStaticMeshComponent* _lookAtPoint;

	UPROPERTY(Transient)
	TMap<TWeakObjectPtr<ADBDPlayer>, FLookingAtData> _authority_overlappingPlayers;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_IsAnyPlayerInTriggerVolume, meta=(AllowPrivateAccess=true))
	bool _isAnyPlayerInTriggerVolume;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_IsAnyPlayerLookingAtPoint, meta=(AllowPrivateAccess=true))
	bool _isAnyPlayerLookingAtPoint;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing=OnRep_WasEventTriggered, meta=(AllowPrivateAccess=true))
	bool _wasEventTriggered;

public:
	UFUNCTION(BlueprintCallable)
	void ResetTriggerConditions();

protected:
	UFUNCTION(BlueprintCallable)
	void OnRep_WasEventTriggered();

	UFUNCTION(BlueprintCallable)
	void OnRep_IsAnyPlayerLookingAtPoint();

	UFUNCTION(BlueprintCallable)
	void OnRep_IsAnyPlayerInTriggerVolume();

	UFUNCTION(BlueprintCallable)
	void OnLevelReadyToPlay();

private:
	UFUNCTION(BlueprintCallable)
	void Authority_OnPlayerExitTriggerVolume(UPrimitiveComponent* overlappedComponent, AActor* otherActor, UPrimitiveComponent* otherComp, int32 otherBodyIndex);

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

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

public:
	ULookAtScriptedEventMapTriggerComponent();
};

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