#ifndef LIVOX_GEN1_INTERNAL_H
#define LIVOX_GEN1_INTERNAL_H

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include <spinscale/co/invokers.h>
#include <user/deviceAttachmentSpec.h>
#include <user/senseApiDesc.h>
#include <user/stimulusProducer.h>

#include "livoxGen1.h"
#include "pcloudStimulusProducer.h"

namespace smo::stim_buff {

struct LivoxProviderParams
{
	int commandTimeoutMs = 5;		// Default: 5ms
	int retryDelayMs = 5250;		// Default: 5250ms
	uint8_t smoSubnetNbits = 24;	// Default: /24 subnet
	uint16_t dataPort = 56000;		// Default data port
	uint16_t cmdPort = 56001;		// Default command port
	uint16_t imuPort = 56002;		// Default IMU port
	std::string smoIp;			// Default: empty string (will trigger IP auto-detection)
};

extern const SmoCallbacks *smoHooksPtr;
extern SmoThreadingModelDesc smoThreadingModelDesc;
extern std::vector<std::shared_ptr<StimulusProducer>> managedStimulusProducers;

void addManagedStimulusProducer(
	const std::shared_ptr<PcloudStimulusProducer> &producer,
	const std::shared_ptr<livoxProto1::Device> &device);

sscl::co::ViralNonPostingInvoker<bool> removeManagedStimulusProducerIfUnused(
	const std::shared_ptr<PcloudStimulusProducer> &producer,
	const std::shared_ptr<sscl::ComponentThread> &componentThread);

std::shared_ptr<StimulusProducer> getStimulusProducer(
	const std::shared_ptr<device::DeviceAttachmentSpec> &spec);

size_t parseNDgramsPerFrame(
	const std::shared_ptr<device::DeviceAttachmentSpec> &spec);

LivoxProviderParams parseLivoxProviderParams(
	const std::shared_ptr<device::DeviceAttachmentSpec> &desc);

bool ensureStimBufferAttachedWithoutDuplicates(
	const std::shared_ptr<PcloudStimulusProducer> &stimProducer,
	const std::shared_ptr<device::DeviceAttachmentSpec> &spec);

sscl::co::ViralNonPostingInvoker<int> livoxGen1_initializeCInd();
sscl::co::ViralNonPostingInvoker<int> livoxGen1_finalizeCInd();

sscl::co::DynamicViralPostingInvoker<StimBuffDeviceOpResult>
livoxGen1_attachDeviceCReq(
	sscl::co::ExplicitPostTarget postTarget,
	const std::shared_ptr<device::DeviceAttachmentSpec> &desc,
	const std::shared_ptr<sscl::ComponentThread> &componentThread);

sscl::co::DynamicViralPostingInvoker<StimBuffDeviceOpResult>
livoxGen1_detachDeviceCReq(
	sscl::co::ExplicitPostTarget postTarget,
	const std::shared_ptr<device::DeviceAttachmentSpec> &desc);

} // namespace smo::stim_buff

#endif // LIVOX_GEN1_INTERNAL_H
