#pragma once

#include "CoreMinimal.h"
#include "HyperTwistTraining/HyperTwistTrainingTilingLibrary.h"
#include "UObject/Object.h"
#include "HyperTwistBrowserBridgeObject.generated.h"

DECLARE_MULTICAST_DELEGATE_OneParam(FHyperTwistBrowserRuntimeReadyDelegate, const FString&);

USTRUCT(BlueprintType)
struct FHyperTwistBrowserRuntimeReadyPayload
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString Status;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString Runtime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString Mode;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 AdapterCount = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString ShellAuthority;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 QueuedCommandCountAtRuntimeReady = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 QueuedShellStateCountAtRuntimeReady = 0;

	bool IsStructurallyValid() const
	{
		return Status.Equals(TEXT("ready"), ESearchCase::CaseSensitive)
			&& !Runtime.IsEmpty() && !Mode.IsEmpty();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistBrowserRuntimeStatusSnapshot
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString RuntimeStatusId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString RuntimeMode;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString BootstrapStartedAtUtc;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString RuntimeReadyAtUtc;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString ShellAuthority;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 AdapterCount = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 QueuedCommandCountAtRuntimeReady = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 QueuedShellStateCountAtRuntimeReady = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 CommandReceiveCount = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	int32 ShellStateReceiveCount = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString LastCommandReceivedAtUtc;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString LastShellStateReceivedAtUtc;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString BridgeTrafficStatus;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString FallbackReason;

	bool IsStructurallyValid() const
	{
		return !RuntimeStatusId.IsEmpty() && !RuntimeMode.IsEmpty();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistBrowserRuntimeStatusEnvelope
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString Type;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FString Source;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Browser")
	FHyperTwistBrowserRuntimeStatusSnapshot Status;

	bool IsStructurallyValid() const
	{
		return Type.Equals(TEXT("browser-runtime-status"), ESearchCase::CaseSensitive)
			&& !Source.IsEmpty() && Status.IsStructurallyValid();
	}
};

UCLASS(BlueprintType)
class UNREALHYPERTWIST_API UHyperTwistBrowserBridgeObject : public UObject
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Browser")
	void NotifyEnvelope(const FString& EnvelopeJson);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Browser")
	void NotifyState(const FString& StateJson);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Browser")
	void NotifyRuntimeReady(const FString& RuntimeReadyJson);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Browser")
	void ResetReceivedMessages();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Browser")
	bool TryGetLastTilingEnvelope(
		FHyperTwistTrainingTilingStateEnvelope& OutStateEnvelope
	) const;

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Browser")
	bool TryGetLastRuntimeReadyPayload(
		FHyperTwistBrowserRuntimeReadyPayload& OutRuntimeReadyPayload
	) const;

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Browser")
	bool TryGetLastTilingStateEnvelope(
		FHyperTwistTrainingTilingStateEnvelope& OutStateEnvelope
	) const;

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Browser")
	bool TryGetLastBrowserRuntimeStatusEnvelope(
		FHyperTwistBrowserRuntimeStatusEnvelope& OutStatusEnvelope
	) const;

	UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Browser")
	FString LastEnvelopeJson;

	UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Browser")
	FString LastStateJson;

	UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Browser")
	FString LastRuntimeReadyJson;

	FHyperTwistBrowserRuntimeReadyDelegate OnRuntimeReady;

	UPROPERTY(Transient)
	FHyperTwistTrainingTilingStateEnvelope LastTilingEnvelope;

	UPROPERTY(Transient)
	FHyperTwistTrainingTilingStateEnvelope LastTilingStateEnvelope;

	UPROPERTY(Transient)
	bool bHasLastTilingEnvelope = false;

	UPROPERTY(Transient)
	bool bHasLastTilingStateEnvelope = false;

	UPROPERTY(Transient)
	FHyperTwistBrowserRuntimeReadyPayload LastRuntimeReadyPayload;

	UPROPERTY(Transient)
	bool bHasLastRuntimeReadyPayload = false;

	UPROPERTY(Transient)
	FHyperTwistBrowserRuntimeStatusEnvelope LastBrowserRuntimeStatusEnvelope;

	UPROPERTY(Transient)
	bool bHasLastBrowserRuntimeStatusEnvelope = false;
};
