#pragma once

#include "GasaCommon.h"
#include "Networking/GasaNetLibrary.h"
#include "UObject/Object.h"
#include "GasaObject.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGasaObjectEventSig);

// A UObject which supports replication and other features.
UCLASS( Blueprintable )
class GASA_API UGasaObject : public UObject
{
	GENERATED_BODY()
public:
	
	UGasaObject();

	UFUNCTION(BlueprintPure)
	FORCEINLINE AActor* GetOwningActor() const { return GetTypedOuter<AActor>(); };
	
	UPROPERTY(BlueprintAssignable, Category="Lifetime")
	FGasaObjectEventSig Event_OnDestroyed;
	
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Lifetime")
	virtual void Destroy();

	virtual void OnDestroyed();

	UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "On Destroyed"))
	void BP_OnDestroyed();

#pragma region Replication
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Replication")
	bool bReplicates;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Replication")
	bool bDisconnectOnBadReplication ;
	
	virtual bool ReplicateAsSubobject(AActor* ActorResponsible, UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags);

	UFUNCTION(BlueprintCallable)
	void SetIsReplicated(bool DesiredValue)
	{
		bReplicates = DesiredValue;
	}
#pragma endregion Replication

#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 UObject
	bool CallRemoteFunction(UFunction* Function, void* Parms, FOutParmRec* OutParms, FFrame* Stack) override;

	int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;

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

	bool IsSupportedForNetworking() const override;
#pragma endregion UObject
};
