#pragma once

#include "CadenceTelemetry.h"
#include "../json/JsonWriter.h"

#include <cstdint>
#include <string>

namespace RenderCadenceCompositor
{
inline void WriteCadenceTelemetryJson(JsonWriter& writer, const CadenceTelemetrySnapshot& snapshot)
{
	writer.BeginObject();
	writer.KeyDouble("sampleSeconds", snapshot.sampleSeconds);
	writer.KeyDouble("renderFps", snapshot.renderFps);
	writer.KeyDouble("scheduleFps", snapshot.scheduleFps);
	writer.KeyUInt("free", static_cast<uint64_t>(snapshot.freeFrames));
	writer.KeyUInt("completed", static_cast<uint64_t>(snapshot.completedFrames));
	writer.KeyUInt("scheduled", static_cast<uint64_t>(snapshot.scheduledFrames));
	writer.KeyUInt("renderedTotal", snapshot.renderedTotal);
	writer.KeyUInt("scheduledTotal", snapshot.scheduledTotal);
	writer.KeyUInt("completedPollMisses", snapshot.completedPollMisses);
	writer.KeyUInt("scheduleFailures", snapshot.scheduleFailures);
	writer.KeyUInt("completedDrops", snapshot.completedDrops);
	writer.KeyUInt("acquireMisses", snapshot.acquireMisses);
	writer.KeyUInt("completions", snapshot.completions);
	writer.KeyUInt("late", snapshot.displayedLate);
	writer.KeyUInt("dropped", snapshot.dropped);
	writer.KeyUInt("clockOverruns", snapshot.clockOverruns);
	writer.KeyUInt("clockSkippedFrames", snapshot.clockSkippedFrames);
	writer.KeyUInt("clockOveruns", snapshot.clockOverruns);
	writer.KeyUInt("clockSkipped", snapshot.clockSkippedFrames);
	writer.KeyUInt("shaderCommitted", snapshot.shaderBuildsCommitted);
	writer.KeyUInt("shaderFailures", snapshot.shaderBuildFailures);
	writer.KeyDouble("renderFrameMs", snapshot.renderFrameMilliseconds);
	writer.KeyDouble("renderFrameBudgetUsedPercent", snapshot.renderFrameBudgetUsedPercent);
	writer.KeyDouble("renderFrameMaxMs", snapshot.renderFrameMaxMilliseconds);
	writer.KeyDouble("readbackQueueMs", snapshot.readbackQueueMilliseconds);
	writer.KeyDouble("completedReadbackCopyMs", snapshot.completedReadbackCopyMilliseconds);
	writer.KeyUInt("inputFramesReceived", snapshot.inputFramesReceived);
	writer.KeyUInt("inputFramesDropped", snapshot.inputFramesDropped);
	writer.KeyUInt("inputConsumeMisses", snapshot.inputConsumeMisses);
	writer.KeyUInt("inputUploadMisses", snapshot.inputUploadMisses);
	writer.KeyUInt("inputReadyFrames", static_cast<uint64_t>(snapshot.inputReadyFrames));
	writer.KeyUInt("inputReadingFrames", static_cast<uint64_t>(snapshot.inputReadingFrames));
	writer.KeyDouble("inputLatestAgeMs", snapshot.inputLatestAgeMilliseconds);
	writer.KeyDouble("inputUploadMs", snapshot.inputUploadMilliseconds);
	writer.KeyBool("inputFormatSupported", snapshot.inputFormatSupported);
	writer.KeyBool("inputSignalPresent", snapshot.inputSignalPresent);
	writer.KeyDouble("inputCaptureFps", snapshot.inputCaptureFps);
	writer.KeyDouble("inputConvertMs", snapshot.inputConvertMilliseconds);
	writer.KeyDouble("inputSubmitMs", snapshot.inputSubmitMilliseconds);
	writer.KeyUInt("inputNoSignalFrames", snapshot.inputNoSignalFrames);
	writer.KeyUInt("inputUnsupportedFrames", snapshot.inputUnsupportedFrames);
	writer.KeyUInt("inputSubmitMisses", snapshot.inputSubmitMisses);
	writer.KeyString("inputCaptureFormat", snapshot.inputCaptureFormat);
	writer.KeyBool("deckLinkBufferedAvailable", snapshot.deckLinkBufferedAvailable);
	writer.Key("deckLinkBuffered");
	if (snapshot.deckLinkBufferedAvailable)
		writer.UInt(snapshot.deckLinkBuffered);
	else
		writer.Null();
	writer.KeyDouble("scheduleCallMs", snapshot.deckLinkScheduleCallMilliseconds);
	writer.KeyBool("deckLinkScheduleLeadAvailable", snapshot.deckLinkScheduleLeadAvailable);
	writer.Key("deckLinkScheduleLeadFrames");
	if (snapshot.deckLinkScheduleLeadAvailable)
		writer.Int(snapshot.deckLinkScheduleLeadFrames);
	else
		writer.Null();
	writer.KeyUInt("deckLinkPlaybackFrameIndex", snapshot.deckLinkPlaybackFrameIndex);
	writer.KeyUInt("deckLinkNextScheduleFrameIndex", snapshot.deckLinkNextScheduleFrameIndex);
	writer.KeyInt("deckLinkPlaybackStreamTime", snapshot.deckLinkPlaybackStreamTime);
	writer.KeyUInt("deckLinkScheduleRealignments", snapshot.deckLinkScheduleRealignments);
	writer.EndObject();
}

inline std::string CadenceTelemetryToJson(const CadenceTelemetrySnapshot& snapshot)
{
	JsonWriter writer;
	WriteCadenceTelemetryJson(writer, snapshot);
	return writer.StringValue();
}
}
