#pragma once


#include "AbilitySystemInterface.h"
#include "GameFramework/PlayerState.h"

#include "GasaCommon.h"
#include "Networking/GasaNetLibrary.h"

#include "GasaPlayerState.generated.h"

UCLASS(Blueprintable)
class GASA_API AGasaPlayerState : public APlayerState
	, public IAbilitySystemInterface
{
	GENERATED_BODY()
public:
	AGasaPlayerState();
	
#pragma region Ability System
	UPROPERTY(EditAnywhere, Category="Ability System")
	bool bAutoAbilitySystem;
	
	UPROPERTY(EditAnywhere, Category="Ability System")
	TObjectPtr<UAbilitySystemComponent> AbilitySystem;

	UPROPERTY(EditAnywhere, Category="Ability System")
	TObjectPtr<UAttributeSet> Attributes;
#pragma endregion Ability System

#pragma region GameFramework
	UFUNCTION()
	void OnGameFrameworkInitialized();

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta = (DisplayName = "On Game Framework Initialized"))
	void BP_OnGameFrameworkInitialized();

	UFUNCTION()
	void OnNetOwnerReady(AGasaPlayerController* PC);

	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, meta = (DisplayName = "On Net Owner Ready"))
	void BP_OnNetOwnerReady();
#pragma endregion GameFramework

#pragma region Networking
#if 0
	UPROPERTY(ReplicatedUsing = Client_OnRep_GasaID)
	int32 GasaID = INDEX_NONE;

	UFUNCTION()
	void Client_OnRep_GasaID;
#endif
#pragma endregion Networking
	
#pragma region NetSlime
	// NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp
	FORCEINLINE ENetworkMode GetNetworkMode() const { return Gasa::GetNetworkMode( this ); }
	FORCEINLINE bool IsClient()               const { return Gasa::IsClient( this ); }
	FORCEINLINE bool IsListenServer()         const { return Gasa::IsListenServer( this ); }
	FORCEINLINE bool IsNetOwner()             const { return Gasa::IsNetOwner( this ); }
	FORCEINLINE bool IsServer()               const { return Gasa::IsServer( this ); }
	FORCEINLINE bool IsSimulatedProxy()       const { return Gasa::IsSimulatedProxy( this ); }
	FORCEINLINE void NetLog(
		FString           Message,
		EGasaVerbosity    Verbosity = EGasaVerbosity::Log,
		FLogCategoryBase& Category  = LogGasaNet,
		bool              DumpStack = false,
		int32             Line      = __builtin_LINE(),
		ANSICHAR const*   File      = __builtin_FILE(),
		ANSICHAR const*   Func      = __builtin_FUNCTION()
	)
	{
		Gasa::NetLog( this, Message, Verbosity, Category, DumpStack, Line, File, Func );
	}
#pragma endregion NetSlime

#pragma region IAbilitySystem
	FORCEINLINE UAttributeSet*           GetAttributes()                            { return Attributes; }
	FORCEINLINE UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystem; }
#pragma endregion IAbilitySystem

#pragma region PlayerState
	void ClientInitialize(AController* C) override;
#pragma endregion PlayerState
	
#pragma region Actor
	void BeginPlay() override;
	void PostInitializeComponents() override;
	void RegisterPlayerWithSession(bool bWasFromInvite) override;
	void Reset() override;
#pragma endregion Actor

#pragma region UObject
	void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
#pragma endregion UObject
};
