#pragma once

#include "DeckLinkSession.h"
#include "VideoIOTypes.h"

#include <atomic>
#include <cstdint>
#include <functional>
#include <string>

namespace RenderCadenceCompositor
{
struct DeckLinkOutputConfig
{
	bool externalKeyingEnabled = false;
	bool outputAlphaRequired = false;
};

struct DeckLinkOutputMetrics
{
	uint64_t completions = 0;
	uint64_t displayedLate = 0;
	uint64_t dropped = 0;
	uint64_t flushed = 0;
	uint64_t scheduleFailures = 0;
	bool actualBufferedFramesAvailable = false;
	uint64_t actualBufferedFrames = 0;
	double scheduleCallMilliseconds = 0.0;
};

class DeckLinkOutput
{
public:
	using CompletionCallback = std::function<void(const VideoIOCompletion&)>;

	DeckLinkOutput() = default;
	DeckLinkOutput(const DeckLinkOutput&) = delete;
	DeckLinkOutput& operator=(const DeckLinkOutput&) = delete;
	~DeckLinkOutput();

	bool Initialize(const DeckLinkOutputConfig& config, CompletionCallback completionCallback, std::string& error);
	bool StartScheduledPlayback(std::string& error);
	bool ScheduleFrame(const VideoIOOutputFrame& frame);
	void Stop();
	void ReleaseResources();

	const VideoIOState& State() const;
	DeckLinkOutputMetrics Metrics() const;

private:
	void HandleCompletion(const VideoIOCompletion& completion);

	DeckLinkSession mSession;
	DeckLinkOutputConfig mConfig;
	CompletionCallback mCompletionCallback;
	std::atomic<uint64_t> mCompletions{ 0 };
	std::atomic<uint64_t> mDisplayedLate{ 0 };
	std::atomic<uint64_t> mDropped{ 0 };
	std::atomic<uint64_t> mFlushed{ 0 };
};
}
