#include "HyperTwistBrowser/HyperTwistBrowserBridgeObject.h"

#include "JsonObjectConverter.h"

namespace HyperTwistBrowserBridgeObjectInternal
{
	bool TryCacheTilingEnvelope(
		const FString& Json,
		FHyperTwistTrainingTilingStateEnvelope& OutEnvelope
	)
	{
		OutEnvelope = FHyperTwistTrainingTilingStateEnvelope();
		return UHyperTwistTrainingTilingLibrary::TryDeserializeStateEnvelopeFromJson(
			Json,
			OutEnvelope
		);
	}

	bool TryCacheBrowserRuntimeStatusEnvelope(
		const FString& Json,
		FHyperTwistBrowserRuntimeStatusEnvelope& OutEnvelope
	)
	{
		OutEnvelope = FHyperTwistBrowserRuntimeStatusEnvelope();
		return !Json.IsEmpty()
			&& FJsonObjectConverter::JsonObjectStringToUStruct(Json, &OutEnvelope, 0, 0)
			&& OutEnvelope.IsStructurallyValid();
	}

	bool TryCacheRuntimeReadyPayload(
		const FString& Json,
		FHyperTwistBrowserRuntimeReadyPayload& OutPayload
	)
	{
		OutPayload = FHyperTwistBrowserRuntimeReadyPayload();
		return !Json.IsEmpty()
			&& FJsonObjectConverter::JsonObjectStringToUStruct(Json, &OutPayload, 0, 0)
			&& OutPayload.IsStructurallyValid();
	}
}

void UHyperTwistBrowserBridgeObject::NotifyEnvelope(const FString& EnvelopeJson)
{
	LastEnvelopeJson = EnvelopeJson;
	bHasLastTilingEnvelope = HyperTwistBrowserBridgeObjectInternal::TryCacheTilingEnvelope(
		EnvelopeJson,
		LastTilingEnvelope
	);

	FHyperTwistBrowserRuntimeStatusEnvelope RuntimeStatusEnvelope;
	if (HyperTwistBrowserBridgeObjectInternal::TryCacheBrowserRuntimeStatusEnvelope(
			EnvelopeJson,
			RuntimeStatusEnvelope
		))
	{
		LastBrowserRuntimeStatusEnvelope = RuntimeStatusEnvelope;
		bHasLastBrowserRuntimeStatusEnvelope = true;
	}
}

void UHyperTwistBrowserBridgeObject::NotifyState(const FString& StateJson)
{
	LastStateJson = StateJson;
	bHasLastTilingStateEnvelope = HyperTwistBrowserBridgeObjectInternal::TryCacheTilingEnvelope(
		StateJson,
		LastTilingStateEnvelope
	);
}

void UHyperTwistBrowserBridgeObject::NotifyRuntimeReady(const FString& RuntimeReadyJson)
{
	LastRuntimeReadyJson = RuntimeReadyJson;

	FHyperTwistBrowserRuntimeReadyPayload RuntimeReadyPayload;
	if (HyperTwistBrowserBridgeObjectInternal::TryCacheRuntimeReadyPayload(
			RuntimeReadyJson,
			RuntimeReadyPayload
		))
	{
		LastRuntimeReadyPayload = RuntimeReadyPayload;
		bHasLastRuntimeReadyPayload = true;
	}

	OnRuntimeReady.Broadcast(RuntimeReadyJson);
}

void UHyperTwistBrowserBridgeObject::ResetReceivedMessages()
{
	LastEnvelopeJson.Reset();
	LastStateJson.Reset();
	LastRuntimeReadyJson.Reset();
	LastTilingEnvelope = FHyperTwistTrainingTilingStateEnvelope();
	LastTilingStateEnvelope = FHyperTwistTrainingTilingStateEnvelope();
	LastRuntimeReadyPayload = FHyperTwistBrowserRuntimeReadyPayload();
	LastBrowserRuntimeStatusEnvelope = FHyperTwistBrowserRuntimeStatusEnvelope();
	bHasLastTilingEnvelope = false;
	bHasLastTilingStateEnvelope = false;
	bHasLastRuntimeReadyPayload = false;
	bHasLastBrowserRuntimeStatusEnvelope = false;
}

bool UHyperTwistBrowserBridgeObject::TryGetLastTilingEnvelope(
	FHyperTwistTrainingTilingStateEnvelope& OutStateEnvelope
) const
{
	OutStateEnvelope = bHasLastTilingEnvelope
		? LastTilingEnvelope
		: FHyperTwistTrainingTilingStateEnvelope();
	return bHasLastTilingEnvelope;
}

bool UHyperTwistBrowserBridgeObject::TryGetLastRuntimeReadyPayload(
	FHyperTwistBrowserRuntimeReadyPayload& OutRuntimeReadyPayload
) const
{
	OutRuntimeReadyPayload = bHasLastRuntimeReadyPayload
		? LastRuntimeReadyPayload
		: FHyperTwistBrowserRuntimeReadyPayload();
	return bHasLastRuntimeReadyPayload;
}

bool UHyperTwistBrowserBridgeObject::TryGetLastTilingStateEnvelope(
	FHyperTwistTrainingTilingStateEnvelope& OutStateEnvelope
) const
{
	OutStateEnvelope = bHasLastTilingStateEnvelope
		? LastTilingStateEnvelope
		: FHyperTwistTrainingTilingStateEnvelope();
	return bHasLastTilingStateEnvelope;
}

bool UHyperTwistBrowserBridgeObject::TryGetLastBrowserRuntimeStatusEnvelope(
	FHyperTwistBrowserRuntimeStatusEnvelope& OutStatusEnvelope
) const
{
	OutStatusEnvelope = bHasLastBrowserRuntimeStatusEnvelope
		? LastBrowserRuntimeStatusEnvelope
		: FHyperTwistBrowserRuntimeStatusEnvelope();
	return bHasLastBrowserRuntimeStatusEnvelope;
}
