#ifndef LIVOXPROTO1_H
#define LIVOXPROTO1_H

#include <memory>
#include <string>
#include <cstdint>
#include <functional>
#include <spinscale/co/invokers.h>
#include <boost/asio/posix/stream_descriptor.hpp>

// Forward declarations
namespace smo {
namespace stim_buff {
	struct SmoCallbacks;
}
}
namespace sscl {
	class ComponentThread;
}

namespace livoxProto1 {
	class Device;
}

struct LivoxProto1GetOrCreateDeviceResult
{
	bool success = false;
	std::shared_ptr<livoxProto1::Device> device;
};

struct LivoxProto1GetReturnModeResult
{
	bool success = false;
	uint8_t returnMode = 0;
};

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Initialize the Livox protocol library
 * @param componentThread Component thread shared pointer
 * @param smoCallbacks Callbacks provided by SMO
 */
typedef void livoxProto1_mainFn(
	const std::shared_ptr<sscl::ComponentThread>& componentThread,
	const smo::stim_buff::SmoCallbacks& smoCallbacks);

/**
 * Cleanup the Livox protocol library
 */
typedef void livoxProto1_exitFn(void);

/**
 * Create a new Livox device connection
 * @param deviceIdentifier The device identifier (broadcast code)
 * @param componentThread Component thread for async operations
 * @param commandTimeoutMs Command timeout in milliseconds (default: 1000)
 * @param retryDelayMs Retry delay in milliseconds (default: 3000)
 * @param smoIp SMO IP address (empty string for auto-detection)
 * @param smoSubnetNbits SMO subnet mask bits (e.g., 24 for /24, 16 for /16)
 * @param dataPort Data port for point cloud (default: 56000)
 * @param cmdPort Command port (default: 56001)
 * @param imuPort IMU port (default: 56002)
 * @return LivoxProto1GetOrCreateDeviceResult (success + device on success,
 *         null device on failure)
 */
typedef sscl::co::ViralNonPostingInvoker<LivoxProto1GetOrCreateDeviceResult>
	livoxProto1_getOrCreateDeviceCReqFn(
	const std::string& deviceIdentifier,
	const std::shared_ptr<sscl::ComponentThread>& componentThread,
	int commandTimeoutMs, int retryDelayMs,
	const std::string& smoIp, uint8_t smoSubnetNbits,
	uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort);

typedef sscl::co::ViralNonPostingInvoker<bool> livoxProto1_destroyDeviceCReqFn(
	std::shared_ptr<livoxProto1::Device> device);

typedef sscl::co::ViralNonPostingInvoker<bool>
	livoxProto1_device_enablePcloudDataCReqFn(
	std::shared_ptr<livoxProto1::Device> device);

typedef sscl::co::ViralNonPostingInvoker<bool>
	livoxProto1_device_disablePcloudDataCReqFn(
	std::shared_ptr<livoxProto1::Device> device);

typedef sscl::co::ViralNonPostingInvoker<LivoxProto1GetReturnModeResult>
	livoxProto1_device_getReturnModeCReqFn(
	std::shared_ptr<livoxProto1::Device> device);

typedef std::shared_ptr<boost::asio::posix::stream_descriptor>
	livoxProto1_getPcloudDataFdDescFn(void);

livoxProto1_mainFn livoxProto1_main;
livoxProto1_exitFn livoxProto1_exit;
livoxProto1_getOrCreateDeviceCReqFn livoxProto1_getOrCreateDeviceCReq;
livoxProto1_destroyDeviceCReqFn livoxProto1_destroyDeviceCReq;
livoxProto1_device_enablePcloudDataCReqFn livoxProto1_device_enablePcloudDataCReq;
livoxProto1_device_disablePcloudDataCReqFn
	livoxProto1_device_disablePcloudDataCReq;
livoxProto1_device_getReturnModeCReqFn livoxProto1_device_getReturnModeCReq;
livoxProto1_getPcloudDataFdDescFn livoxProto1_getPcloudDataFdDesc;

#ifdef __cplusplus
}
#endif

#endif // LIVOXPROTO1_H
