#pragma once

#include "VideoIOTypes.h"
#include "VideoPlayoutPolicy.h"

#include <cstdint>
#include <deque>
#include <functional>
#include <mutex>

struct RenderOutputFrame
{
	VideoIOOutputFrame frame;
	uint64_t frameIndex = 0;
	bool stale = false;
	std::function<void(VideoIOOutputFrame& frame)> releaseFrame;
};

struct RenderOutputQueueMetrics
{
	std::size_t depth = 0;
	std::size_t capacity = 0;
	uint64_t pushedCount = 0;
	uint64_t poppedCount = 0;
	uint64_t droppedCount = 0;
	uint64_t underrunCount = 0;
};

class RenderOutputQueue
{
public:
	explicit RenderOutputQueue(const VideoPlayoutPolicy& policy = VideoPlayoutPolicy());

	void Configure(const VideoPlayoutPolicy& policy);
	bool Push(RenderOutputFrame frame);
	bool TryPop(RenderOutputFrame& frame);
	bool DropOldestFrame();
	void Clear();
	RenderOutputQueueMetrics GetMetrics() const;

private:
	std::size_t CapacityLocked() const;
	static void ReleaseFrame(RenderOutputFrame& frame);

	mutable std::mutex mMutex;
	VideoPlayoutPolicy mPolicy;
	std::deque<RenderOutputFrame> mReadyFrames;
	uint64_t mPushedCount = 0;
	uint64_t mPoppedCount = 0;
	uint64_t mDroppedCount = 0;
	uint64_t mUnderrunCount = 0;
};
