#ifndef _LIVOX_GEN1_PCLOUD_LIGHT_AMBIENCE_STIMULUS_BUFFER_H
#define _LIVOX_GEN1_PCLOUD_LIGHT_AMBIENCE_STIMULUS_BUFFER_H

#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <user/deviceAttachmentSpec.h>
#include <user/intrin.h>
#include <user/intrinThresholdParams.h>
#include <user/stagingBuffer.h>
#include <user/stimulusBuffer.h>
#include "pcloudAmbienceQualeIfaceApi.h"

namespace smo {
namespace stim_buff {

class StimulusProducer;

/**
 * Sensory pcloudLightAmbience buffer: one uint32 stimspot per stimframe —
 * the count of per-frame slots whose average intensity exceeds the
 * qualeIface's passband-count-gt-val. A DAP spec may optionally attach a
 * negtrin(...) specifier (scene is "unbearably much, get away"); postrin
 * is not valid on this qualeIfaceApi.
 */
class PcloudLightAmbienceStimulusBuffer
:	public StimulusBuffer
{
public:
	explicit PcloudLightAmbienceStimulusBuffer(
		StimulusProducer& parent,
		const std::shared_ptr<device::DeviceAttachmentSpec>& deviceAttachmentSpec,
		int histbuffMs,
		const StagingBuffer::IOEngineConstraints& inputEngineConstraints,
		const StagingBuffer::IOEngineConstraints& outputEngineConstraints,
		const SmoCallbacks& callbacks,
		cl_mem_flags flags,
		size_t nDgramsPerFrame_)
	:	StimulusBuffer(
			parent, deviceAttachmentSpec, histbuffMs,
			inputEngineConstraints, outputEngineConstraints,
			callbacks, flags),
	nDgramsPerFrame(nDgramsPerFrame_)
	{
		intrin::validateNoIntrinParamsOnQualeIface(
			deviceAttachmentSpec->qualeIfaceApi,
			deviceAttachmentSpec->qualeIfaceApiParams);

		passbandCountGtComparator =
			parsePcloudLightAmbienceGtComparator(deviceAttachmentSpec);

		if (!deviceAttachmentSpec->postrin.empty())
		{
			throw std::runtime_error(
				"pcloudLightAmbience DAP spec for device '"
				+ deviceAttachmentSpec->deviceIdentifier
				+ "' declares a postrin(...); postrin belongs on a "
				"pcloudDarkAmbience line, not pcloudLightAmbience.");
		}

		if (!deviceAttachmentSpec->negtrin.empty())
		{
			negtrinInterestConfig = parseAmbienceIntrinConfigFromParams(
				"negtrin",
				deviceAttachmentSpec->negtrinParams,
				nDgramsPerFrame_);
		}
	}

	~PcloudLightAmbienceStimulusBuffer() = default;

	PcloudLightAmbienceStimulusBuffer(
		const PcloudLightAmbienceStimulusBuffer&) = delete;
	PcloudLightAmbienceStimulusBuffer& operator=(
		const PcloudLightAmbienceStimulusBuffer&) = delete;
	PcloudLightAmbienceStimulusBuffer(
		PcloudLightAmbienceStimulusBuffer&&) = delete;
	PcloudLightAmbienceStimulusBuffer& operator=(
		PcloudLightAmbienceStimulusBuffer&&) = delete;

	bool shouldTriggerNegtrinEvent(uint32_t ambiencePassbandCount) const
	{
		if (!negtrinInterestConfig.has_value()) { return false; }
		return ambiencePassbandCount >= negtrinInterestConfig->threshold;
	}

public:
	size_t nDgramsPerFrame;
	ParamComparator passbandCountGtComparator;
	std::optional<intrin::IntrinConfig> negtrinInterestConfig;
};

} // namespace stim_buff
} // namespace smo

#endif // _LIVOX_GEN1_PCLOUD_LIGHT_AMBIENCE_STIMULUS_BUFFER_H
