#ifndef TESTHOST_PERFORMANCESTATS_H_INCLUDED
#define TESTHOST_PERFORMANCESTATS_H_INCLUDED

#include <JuceHeader.h>
#include <cstdio>

/** Timing instrumentation around processBlock() calls.

	This never paces the render loop to real-time - the entire point of a
	headless host is to run faster than real-time - it only measures how
	fast processBlock() actually ran, so regressions in render cost show up
	without needing a GUI or a live audio device.
*/
class PerformanceStats
{
public:
	PerformanceStats() {}

	void reset (double sampleRateToUse)
	{
		sampleRate = sampleRateToUse;
		blockTimesMs.clearQuick();
		totalSamples = 0;
	}

	/** Wrap the call you want timed: stats.timeBlock(numSamples, [&]{ host.process(buffer, midi); }); */
	template <typename Callable>
	void timeBlock (int numSamples, Callable &&call)
	{
		const double start = Time::getMillisecondCounterHiRes();
		call();
		const double elapsedMs = Time::getMillisecondCounterHiRes() - start;

		blockTimesMs.add (elapsedMs);
		totalSamples += numSamples;
	}

	void printSummary() const
	{
		if (blockTimesMs.size() == 0)
			return;

		double sumMs = 0.0, minMs = blockTimesMs.getUnchecked (0), maxMs = blockTimesMs.getUnchecked (0);
		for (int i = 0; i < blockTimesMs.size(); ++i)
		{
			const double t = blockTimesMs.getUnchecked (i);
			sumMs += t;
			minMs = jmin (minMs, t);
			maxMs = jmax (maxMs, t);
		}
		const double meanMs = sumMs / blockTimesMs.size();

		const double audioSeconds = totalSamples / sampleRate;
		const double wallSeconds = sumMs / 1000.0;
		const double realTimeFactor = wallSeconds > 0.0 ? audioSeconds / wallSeconds : 0.0;

		printf ("testhost: performance - %d blocks, render time min/mean/max = %.3f/%.3f/%.3f ms, "
			"%.3fs audio rendered in %.3fs wall time (%.1fx real-time)\n",
			blockTimesMs.size(), minMs, meanMs, maxMs, audioSeconds, wallSeconds, realTimeFactor);
	}

	/** Optional: one row per block, for tracking regressions over time in CI. */
	bool writeCsv (const File &destFile) const
	{
		StringArray lines;
		lines.add ("blockIndex,renderTimeMs");
		for (int i = 0; i < blockTimesMs.size(); ++i)
			lines.add (String (i) + "," + String (blockTimesMs.getUnchecked (i), 6));

		return destFile.replaceWithText (lines.joinIntoString ("\n") + "\n");
	}

private:
	double sampleRate = 44100.0;
	Array<double> blockTimesMs;
	int64 totalSamples = 0;
};

#endif // TESTHOST_PERFORMANCESTATS_H_INCLUDED
