#ifndef _LIVOX_GEN1_PCLOUD_STIMULUS_PRODUCER_H
#define _LIVOX_GEN1_PCLOUD_STIMULUS_PRODUCER_H

#include <functional>
#include <atomic>
#include <optional>
#include <exception>
#include <user/stimulusProducer.h>
#include <user/stimulusFrame.h>
#include <livoxProto1/device.h>
#include <spinscale/co/invokers.h>
#include <user/stagingBuffer.h>
#include "ioUringAssemblyEngine.h"
#include "livoxPcloudFrameDumper.h"
#include "openClCollatingAndMeshingEngine.h"
#include "meshStimulusBuffer.h"
#include "pcloudIntensityStimulusBuffer.h"
#include "pcloudLightAmbienceStimulusBuffer.h"
#include "pcloudDarkAmbienceStimulusBuffer.h"

namespace smo {
namespace stim_buff {

/**
 * PcloudStimulusProducer is a specialized StimulusProducer for point cloud data.
 *
 * This class extends StimulusProducer to handle point cloud-specific stimulus
 * frames, particularly those generated from LiDAR point cloud data. It
 * provides additional functionality for managing point cloud frame metadata
 * and processing.
 */
class PcloudStimulusProducer
:	public StimulusProducer
{
public:
	class PcloudFormatDesc
	{
	public:
		enum class Format
		{
			XYZ,
			XYZI,
		};

	public:
		Format format;
	};

public:
	explicit PcloudStimulusProducer(
		const std::shared_ptr<device::DeviceAttachmentSpec> &deviceAttachmentSpec,
		std::shared_ptr<livoxProto1::Device> &device,
		const PcloudFormatDesc& formatDesc,
		size_t nDgramsPerStagingBufferFrame);

	~PcloudStimulusProducer() = default;

	// Non-copyable, non-movable: pinners hold buffer instance references
	PcloudStimulusProducer(const PcloudStimulusProducer&) = delete;
	PcloudStimulusProducer& operator=(const PcloudStimulusProducer&) = delete;
	PcloudStimulusProducer(PcloudStimulusProducer&&) = delete;
	PcloudStimulusProducer& operator=(PcloudStimulusProducer&&) = delete;

	// Control methods
	void start() override;
	void stop() override;

	static bool supportsQualeIfaceApi(const std::string& qualeIfaceApi);

	bool exportsQualeIfaceApi(
		const std::string& qualeIfaceApi) const override;

	std::shared_ptr<StimulusBuffer> getOrCreateAttachedStimulusBuffer(
		const std::shared_ptr<device::DeviceAttachmentSpec>
			&deviceAttachmentSpec) override;

	std::shared_ptr<StimulusBuffer> getAttachedStimulusBuffer(
		const std::shared_ptr<device::DeviceAttachmentSpec>& spec)
		const override;

	void destroyAttachedStimulusBuffer(
		const std::shared_ptr<StimulusBuffer>& buffer) override;

protected:
	sscl::co::ViralNonPostingInvoker<void>
		stimFrameProductionTimesliceCInd(
			sscl::SyncCancelerForAsyncWork &canceler) override;

public:
	size_t nDgramsPerStagingBufferFrame;
	std::shared_ptr<livoxProto1::Device> device;
	PcloudFormatDesc formatDesc;
	OpenClCollatingAndMeshingEngine openClCollatingAndMeshingEngine;
	StagingBuffer assemblyBuffer;
	IoUringAssemblyEngine ioUringAssemblyEngine;
	StagingBuffer collationBuffer;
	std::unique_ptr<StagingBuffer::MlockPinner> collationBufferMlockPinner;
	StagingBuffer averageIntensityBuffer;
	std::unique_ptr<StagingBuffer::MlockPinner>
		averageIntensityBufferMlockPinner;
	LivoxPcloudFrameDumper pcloudFrameDumper;
	size_t tempStimulusFrameMem;
	StimulusFrame tempStimulusFrame;
	std::atomic<std::shared_ptr<MeshStimulusBuffer>> meshStimulusBuffer;
	std::atomic<std::shared_ptr<PcloudIntensityStimulusBuffer>>
		intensityStimulusBuffer;
	std::atomic<std::shared_ptr<PcloudLightAmbienceStimulusBuffer>>
		lightAmbienceStimulusBuffer;
	std::atomic<std::shared_ptr<PcloudDarkAmbienceStimulusBuffer>>
		darkAmbienceStimulusBuffer;
};

} // namespace stim_buff
} // namespace smo

#endif // _LIVOX_GEN1_PCLOUD_STIMULUS_PRODUCER_H
