#pragma once

#include "RuntimeCoordinator.h"
#include "RuntimeEventPayloads.h"

#include <cstddef>
#include <cstdint>
#include <string>

class RenderEngine;
struct RuntimeEvent;
struct RuntimeEventDispatchResult;
class RuntimeEventDispatcher;
class RuntimeServices;
class RuntimeStore;
class ShaderBuildQueue;
class VideoBackend;

class RuntimeUpdateController
{
public:
	RuntimeUpdateController(
		RuntimeStore& runtimeStore,
		RuntimeCoordinator& runtimeCoordinator,
		RuntimeEventDispatcher& runtimeEventDispatcher,
		RuntimeServices& runtimeServices,
		RenderEngine& renderEngine,
		ShaderBuildQueue& shaderBuildQueue,
		VideoBackend& videoBackend);

	bool ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error = nullptr);
	bool ProcessRuntimeWork();
	void RequestShaderBuild();
	void BroadcastRuntimeState();

private:
	void HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event);
	void HandleRuntimeReloadRequested(const RuntimeEvent& event);
	void HandleRuntimePersistenceRequested(const RuntimeEvent& event);
	void HandleShaderBuildRequested(const RuntimeEvent& event);
	void HandleShaderBuildPrepared(const RuntimeEvent& event);
	void HandleShaderBuildFailed(const RuntimeEvent& event);
	void HandleCompileStatusChanged(const RuntimeEvent& event);
	void HandleRenderResetRequested(const RuntimeEvent& event);
	bool ConsumeReadyShaderBuild(uint64_t expectedGeneration, bool publishPreparedEvent, bool publishFailureEvent);
	void PublishShaderBuildLifecycleEvent(
		RuntimeEventShaderBuildPhase phase,
		uint64_t generation,
		unsigned inputWidth,
		unsigned inputHeight,
		bool succeeded,
		const std::string& message);
	bool ShouldSuppressCoordinatorFollowUp(const RuntimeEvent& event, std::size_t& pendingSuppressions);
	RuntimeEventDispatchResult DispatchRuntimeEvents(std::size_t maxEvents = 0);
	void PublishRuntimeEventHealthObservations(const RuntimeEventDispatchResult& result);

	RuntimeStore& mRuntimeStore;
	RuntimeCoordinator& mRuntimeCoordinator;
	RuntimeEventDispatcher& mRuntimeEventDispatcher;
	RuntimeServices& mRuntimeServices;
	RenderEngine& mRenderEngine;
	ShaderBuildQueue& mShaderBuildQueue;
	VideoBackend& mVideoBackend;
	std::size_t mPendingCoordinatorShaderBuildEvents = 0;
	std::size_t mPendingCoordinatorCompileStatusEvents = 0;
	std::size_t mPendingCoordinatorRenderResetEvents = 0;
	std::size_t mLastReportedRuntimeEventQueueDepth = static_cast<std::size_t>(-1);
	std::size_t mLastReportedRuntimeEventDroppedCount = static_cast<std::size_t>(-1);
	std::size_t mLastReportedRuntimeEventCoalescedCount = static_cast<std::size_t>(-1);
};
