#pragma once

#include "CoreMinimal.h"
#include "ChainLinkable.h"
#include "Components/ActorComponent.h"
#include "Templates/SubclassOf.h"
#include "TagStateBool.h"
#include "ChainLinkableComponent.generated.h"

class UBaseCameraTargetingStrategy;
class UPlayerReelInputAccelerationConstraintStrategy;
class AKiller;
class URiflePlayerLinker;
class UStatusEffect;
class UChainPlayerMovementStatusEffect;

UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
class THEGUNSLINGER_API UChainLinkableComponent : public UActorComponent, public IChainLinkable
{
	GENERATED_BODY()

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<UBaseCameraTargetingStrategy> _cameraTargetingStrategyClass;

	UPROPERTY(BlueprintReadWrite, Transient, Instanced)
	UPlayerReelInputAccelerationConstraintStrategy* _inputAccelerationStrategy;

	UPROPERTY(BlueprintReadWrite, ReplicatedUsing=OnRep_OwningKiller, Transient)
	AKiller* _owningKiller;

private:
	UPROPERTY(BlueprintReadWrite, Transient, Instanced, meta=(AllowPrivateAccess=true))
	URiflePlayerLinker* _chainLink;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<UStatusEffect> _movementStatusEffectClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess=true))
	TSubclassOf<UStatusEffect> _linkedStatusEffectClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, meta=(AllowPrivateAccess=true))
	FTagStateBool _isLinkedLingering;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Instanced, meta=(AllowPrivateAccess=true))
	UChainPlayerMovementStatusEffect* _movementStatusEffect;

	UPROPERTY(BlueprintReadWrite, Transient, meta=(AllowPrivateAccess=true))
	UBaseCameraTargetingStrategy* _cameraStrategy;

private:
	UFUNCTION(BlueprintCallable)
	void OnRep_OwningKiller();

protected:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void OnKillerSet(AKiller* killer);

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

public:
	UChainLinkableComponent();
};

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