#ifndef _STIMULUS_BUFFER_H
#define _STIMULUS_BUFFER_H

#include <config.h>
#include <vector>
#include <memory>
#include <user/spMcRingBuffer.h>
#include <user/stagingBuffer.h>
#include <user/frameAssemblyDesc.h>
#include <user/senseApiDesc.h>
#include "stimulusFrame.h"
#include "deviceAttachmentSpec.h"
#define CL_TARGET_OPENCL_VERSION 120
#include <CL/cl.h>

namespace smo {
namespace stim_buff {

// Forward declaration
class StimulusProducer;

/**
 * StimulusBuffer manages a collection of stimulus frames and ring buffer.
 *
 * This buffer holds the actual frame storage and ring buffer for stimulus
 * data. It maintains a reference to its parent StimulusProducer.
 */
class StimulusBuffer
{
public:
	explicit StimulusBuffer(
		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)
	: parent(parent),
	deviceAttachmentSpec(deviceAttachmentSpec),
	histbuffMs(histbuffMs),
	stagingBuffer(
		inputEngineConstraints,
		outputEngineConstraints,
		static_cast<size_t>(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS)),
	stagingBufferPinner(stagingBuffer.makeMlockPinner()),
	ringBuffer(
		static_cast<std::shared_ptr<FrameAssemblyDesc>>(stagingBuffer),
		callbacks, flags)
	{}

	virtual ~StimulusBuffer() = default;

	// Non-copyable, non-movable: pinner lifetime is tied to this instance
	StimulusBuffer(const StimulusBuffer&) = delete;
	StimulusBuffer& operator=(const StimulusBuffer&) = delete;
	StimulusBuffer(StimulusBuffer&&) = delete;
	StimulusBuffer& operator=(StimulusBuffer&&) = delete;

public:
	StimulusProducer& parent;
	std::shared_ptr<device::DeviceAttachmentSpec> deviceAttachmentSpec;
	int histbuffMs;
	StagingBuffer stagingBuffer;
	std::unique_ptr<StagingBuffer::MlockPinner> stagingBufferPinner;
	SpMcRingBuffer ringBuffer;
};

} // namespace stim_buff
} // namespace smo

#endif // _STIMULUS_BUFFER_H
