#include "PulseLengthStatAnalyzer.h"
#include "PulseLengthStatAnalyzerSettings.h"
#include <AnalyzerChannelData.h>

// One frame per stable level between edges. mData1 = duration in samples; mFlags: 1 = HIGH, 0 = LOW.

PulseLengthStatAnalyzer::PulseLengthStatAnalyzer()
	: Analyzer2(),
	  mSettings(),
	  mSimulationInitilized(false)
{
	SetAnalyzerSettings(&mSettings);
}

PulseLengthStatAnalyzer::~PulseLengthStatAnalyzer()
{
	KillThread();
}

void PulseLengthStatAnalyzer::SetupResults()
{
	mResults.reset(new PulseLengthStatAnalyzerResults(this, &mSettings));
	SetAnalyzerResults(mResults.get());
	mResults->AddChannelBubblesWillAppearOn(mSettings.mInputChannel);
}

void PulseLengthStatAnalyzer::WorkerThread()
{
	mChannelData = GetAnalyzerChannelData(mSettings.mInputChannel);

	U32 frames_since_commit = 0;
	const U32 kCommitBatch = 256;

	for (;;)
	{
		CheckIfThreadShouldExit();

		const U64 segment_start = mChannelData->GetSampleNumber();
		const BitState level = mChannelData->GetBitState();

		mChannelData->AdvanceToNextEdge();

		const U64 edge_sample = mChannelData->GetSampleNumber();
		if (edge_sample == segment_start)
			break;

		const U64 duration_samples = edge_sample - segment_start;
		const U64 end_inclusive = edge_sample > segment_start ? edge_sample - 1 : segment_start;

		Frame frame;
		frame.mData1 = duration_samples;
		frame.mFlags = (level == BIT_HIGH) ? 1 : 0;
		frame.mStartingSampleInclusive = static_cast<S64>(segment_start);
		frame.mEndingSampleInclusive = static_cast<S64>(end_inclusive);

		mResults->AddFrame(frame);
		if (++frames_since_commit >= kCommitBatch)
		{
			mResults->CommitResults();
			frames_since_commit = 0;
		}
		ReportProgress(edge_sample);
	}

	if (frames_since_commit != 0)
		mResults->CommitResults();
}

bool PulseLengthStatAnalyzer::NeedsRerun()
{
	return false;
}

U32 PulseLengthStatAnalyzer::GenerateSimulationData(U64 minimum_sample_index, U32 device_sample_rate,
													SimulationChannelDescriptor** simulation_channels)
{
	if (mSimulationInitilized == false)
	{
		mSimulationDataGenerator.Initialize(GetSimulationSampleRate(), &mSettings);
		mSimulationInitilized = true;
	}

	return mSimulationDataGenerator.GenerateSimulationData(minimum_sample_index, device_sample_rate,
															simulation_channels);
}

U32 PulseLengthStatAnalyzer::GetMinimumSampleRateHz()
{
	return 200000;
}

const char* PulseLengthStatAnalyzer::GetAnalyzerName() const
{
	return "Pulse Length Stat";
}

const char* GetAnalyzerName()
{
	return "Pulse Length Stat";
}

Analyzer* CreateAnalyzer()
{
	return new PulseLengthStatAnalyzer();
}

void DestroyAnalyzer(Analyzer* analyzer)
{
	delete analyzer;
}
