#pragma once

#include "CoreMinimal.h"
#include "AIInteractableTargetInterface.h"
#include "ContainsItemInterface.h"
#include "Interactable.h"
#include "Searchable.generated.h"

class USearchableItemStrategy;
class USearchableSpawnPoint;
class ACollectable;
class ADBDPlayer;
class UBlockableComponent;
class ULocalPlayerTrackerComponent;
class UPrimitiveComponent;

UCLASS(Blueprintable)
class DEADBYDAYLIGHT_API ASearchable : public AInteractable, public IAIInteractableTargetInterface, public IContainsItemInterface
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSearchedChanged, bool, searched);

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Weight;

	UPROPERTY(BlueprintReadWrite, BlueprintAssignable)
	FOnSearchedChanged OnSearchedChanged;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced)
	USearchableItemStrategy* SearchableItemStrategy;

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, meta=(AllowPrivateAccess=true))
	USearchableSpawnPoint* _searchableSpawnPoint;

	UPROPERTY(BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	ACollectable* _spawnedItem;

	UPROPERTY(BlueprintReadWrite, Replicated, Transient, meta=(AllowPrivateAccess=true))
	ACollectable* _itemInsideSearchable;

	UPROPERTY(BlueprintReadWrite, ReplicatedUsing=OnRep_IsOpened, Transient, meta=(AllowPrivateAccess=true))
	bool _isOpened;

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

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	TMap<ADBDPlayer*, uint8> _numberOfSearchesWhileOpenPerPlayer;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	UBlockableComponent* _searchableBlockableComponent;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	ULocalPlayerTrackerComponent* _localPlayerTracker;

public:
	UFUNCTION(BlueprintCallable)
	void SetHasBeenSearched(bool newHasBeenSearched);

private:
	UFUNCTION(BlueprintCallable)
	void OnSearchableBlockChanged();

	UFUNCTION(BlueprintCallable)
	void OnRep_IsOpened();

	UFUNCTION(BlueprintCallable)
	void OnLocallyObservedChanged();

public:
	UFUNCTION(BlueprintCallable, NetMulticast, Reliable)
	void Multicast_SetHasBeenSearched(bool hasBeenSearched);

	UFUNCTION(BlueprintPure)
	bool IsSearchableBlockedForPlayer(const ADBDPlayer* player) const;

	UFUNCTION(BlueprintPure)
	bool HasBeenSearched() const;

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

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnUnblockSearchable(ADBDPlayer* player);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, BlueprintCosmetic)
	void Cosmetic_OnBlockSearchable(ADBDPlayer* player);

public:
	UFUNCTION(BlueprintCallable)
	bool ContainsSpawnedItem() const;

	UFUNCTION(BlueprintCallable)
	ACollectable* Authority_SpawnObject(ADBDPlayer* player);

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

public:
	ASearchable();
};

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