#ifndef _LIVOX_GEN1_IOURING_ASSEMBLY_ENGINE_H
#define _LIVOX_GEN1_IOURING_ASSEMBLY_ENGINE_H

#include <cstdint>
#include <cstddef>
#include <memory>
#include <functional>
#include <vector>
#include <chrono>
#include <atomic>

#include <livoxProto1/device.h>

#include "frameAssemblyDesc.h"

namespace smo {
namespace stim_buff {

class IoUringAssemblyEngine
{
public:
	using FrameCompleteCallback = std::function<void(size_t /*frameIndex*/)>;

	IoUringAssemblyEngine();
	~IoUringAssemblyEngine();

	// Configure UDP socket by querying the device's pcloud data socket descriptor
	bool setSocketFromDevice(const std::shared_ptr<livoxProto1::Device>& device);

	// Start posting N RECVMSG SQEs based on the descriptor; timeoutMs defaults to 15ms
	bool start(
		FrameAssemblyDesc& desc,
		uint8_t* frameBase,
		size_t frameStrideBytes,
		uint32_t timeoutMs = 15);

	void pause();
	void resume();
	void stop();

	void onFrameComplete(FrameCompleteCallback cb);

    // Telemetry helpers
    static size_t computePointsPerDgram(int returnMode);
    static size_t computePointsPerFrame(int returnMode, size_t nDgramsPerFrame)
		{ return computePointsPerDgram(returnMode) * nDgramsPerFrame; }

private:
    int udpFd;
    std::atomic<bool> running;
    std::atomic<bool> paused;
    FrameCompleteCallback frameCb;

	// Cached descriptor for reuse across iterations
    FrameAssemblyDesc* desc;
    uint8_t* frameBase;
    size_t frameStrideBytes;
    uint32_t timeoutMs;
    size_t frameIndex;

	// Internal helpers
	void postReceives();
	void handleCqesAndTimeout();
	void cancelIncompleteAndFillDummies();
};

} // namespace stim_buff
} // namespace smo

#endif // _LIVOX_GEN1_IOURING_ASSEMBLY_ENGINE_H


