#pragma once

#include "CoreMinimal.h"
#include "PotentialAttack.h"
#include "GameFramework/Actor.h"
#include "DBDTunableRowHandle.h"
#include "GameplayTagContainer.h"
#include "Templates/SubclassOf.h"
#include "Engine/HitResult.h"
#include "HalloweenHaunt.generated.h"

class USkeletalMeshComponent;
class UCapsuleComponent;
class UCurveFloat;
class ABaseProjectile;
class ADBDPlayer;
class UPrimitiveComponent;

UCLASS(Blueprintable, Abstract)
class HALLOWEEN_API AHalloweenHaunt : public AActor, public IPotentialAttack
{
	GENERATED_BODY()

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	USkeletalMeshComponent* _skeletalMesh;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UCapsuleComponent* _worldCollider;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	UCapsuleComponent* _playerCollider;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FDBDTunableRowHandle _maximumTravelSpeed;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UCurveFloat* _travelingMovementCurve;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FGameplayTagContainer _tagsPreventingPlayerHit;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TArray<TSubclassOf<AActor>> _actorsToIgnore;

	UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Transient)
	TSet<ABaseProjectile*> _cachedProjectilesInGame;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float _timeToDisappear;

public:
	UFUNCTION(BlueprintCallable)
	void SetHauntHidden(const bool isHidden);

protected:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_StartDisappearHaunt();

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnPlayerHit(ADBDPlayer* playerHit);

	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_OnActorHit(AActor* actorHit);

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnPlayerHit(ADBDPlayer* playerHit);

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

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

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnCollisionHit(AActor* actorHit);

	UFUNCTION()
	void Authority_OnCollisionOverlapBegin(UPrimitiveComponent* overlappedComp, AActor* otherActor, UPrimitiveComponent* otherComp, int32 otherBodyIndex, bool fromSweep, const FHitResult& sweepResult);

public:
	AHalloweenHaunt();
};

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