#include "HyperTwistRecognition/HyperTwistVisionClient.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

bool UHyperTwistMockVisionClient::OpenVisionSession(const FHyperTwistVisionSessionConfig& Config, FString& OutError)
{
	OutError.Reset();

	if (Config.SessionId.IsEmpty())
	{
		OutError = TEXT("session-id-required");
		return false;
	}

	SessionConfigs.Add(Config.SessionId, Config);
	SessionFrameCounts.Add(Config.SessionId, 0);
	return true;
}

FHyperTwistVisionPreviewResult UHyperTwistMockVisionClient::SubmitVisionFrame(const FHyperTwistVisionFrameEnvelope& Frame)
{
	FHyperTwistVisionPreviewResult Result = UHyperTwistContractLibrary::MakeMockVisionPreviewResult();
	Result.SessionId = Frame.SessionId;
	Result.FrameId = Frame.FrameId;
	Result.PreviewState.State.SourceSessionId = Frame.SessionId;

	const int32 NextFrameCount = SessionFrameCounts.FindRef(Frame.SessionId) + 1;
	SessionFrameCounts.Add(Frame.SessionId, NextFrameCount);
	Result.Guidance = NextFrameCount >= 3 ? TEXT("commit-ready") : TEXT("keep-scanning");

	return Result;
}

FHyperTwistVisionCommitResult UHyperTwistMockVisionClient::CommitVisionObservation(const FHyperTwistVisionCommitRequest& Request)
{
	FHyperTwistVisionCommitResult Result = UHyperTwistContractLibrary::MakeMockVisionCommitResult();
	Result.SessionId = Request.SessionId;
	Result.CommitKind = Request.CommitKind;
	Result.CommittedUnit = !Request.TargetFace.IsEmpty() ? Request.TargetFace : Request.TargetStage;
	Result.Snapshot.State.SourceSessionId = Request.SessionId;

	if (!SessionConfigs.Contains(Request.SessionId))
	{
		Result.Warnings.Add(TEXT("session-not-open"));
		Result.Confidence = 0.0f;
	}

	return Result;
}

FHyperTwistVisionFinalizeResult UHyperTwistMockVisionClient::FinalizeVisionSession(const FString& SessionId)
{
	FHyperTwistVisionFinalizeResult Result = UHyperTwistContractLibrary::MakeMockVisionFinalizeResult();
	Result.SessionId = SessionId;
	Result.FinalState.SourceSessionId = SessionId;
	Result.FinalSnapshot.State.SourceSessionId = SessionId;

	if (!SessionConfigs.Contains(SessionId))
	{
		Result.NormalizationWarnings.Add(TEXT("session-not-open"));
	}
	else
	{
		SessionConfigs.Remove(SessionId);
		SessionFrameCounts.Remove(SessionId);
	}

	return Result;
}

bool UHyperTwistMockVisionClient::CloseVisionSession(const FString& SessionId, FString& OutError)
{
	OutError.Reset();

	if (!SessionConfigs.Contains(SessionId))
	{
		OutError = TEXT("session-not-open");
		return false;
	}

	SessionConfigs.Remove(SessionId);
	SessionFrameCounts.Remove(SessionId);
	return true;
}

FHyperTwistVisionServiceHealth UHyperTwistMockVisionClient::GetVisionServiceHealth() const
{
	FHyperTwistVisionServiceHealth Health = UHyperTwistContractLibrary::MakeMockVisionServiceHealth();
	Health.ProviderLabel = TEXT("mock");
	Health.ServiceEndpoint = TEXT("in-process://mock");
	Health.Capabilities.Add(TEXT("sessioned-mock-client"));
	return Health;
}
