#ifndef LCAMERA_BUFF_INTERNAL_H
#define LCAMERA_BUFF_INTERNAL_H

#include <lcameraDev.h>
#include <memory>
#include <user/deviceAttachmentSpec.h>
#include <user/senseApiDesc.h>
#include <vector>
#include <spinscale/co/invokers.h>

namespace smo::stim_buff::lcamera_buff {

class YuvStimProducer;

struct LcameraDevDllState
{
	struct DlCloser
	{
		void operator()(void *handle);
	};

	LcameraDevDllState();

	std::unique_ptr<void, DlCloser> dlopenHandle;
	lcameraDev_mainFn *lcameraDev_main;
	lcameraDev_exitFn *lcameraDev_exit;
	lcameraDev_getOrCreateDeviceCReqFn *lcameraDev_getOrCreateDeviceCReq;
	lcameraDev_resolveDeviceSelectorCReqFn *lcameraDev_resolveDeviceSelectorCReq;
	lcameraDev_releaseDeviceCReqFn *lcameraDev_releaseDeviceCReq;
	lcameraDev_configureSessionModeCReqFn *lcameraDev_configureSessionModeCReq;
};

extern const SmoCallbacks *lcameraBuffSmoHooksPtr;
extern SmoThreadingModelDesc lcameraBuffThreadingModelDesc;
extern LcameraDevDllState lcameraDevDll;
extern std::vector<std::shared_ptr<YuvStimProducer>> managedStimulusProducers;

void addManagedStimulusProducer(
	const std::shared_ptr<YuvStimProducer>& producer);

sscl::co::ViralNonPostingInvoker<void> removeManagedStimulusProducerIfUnused(
	const std::shared_ptr<YuvStimProducer>& producer);

std::shared_ptr<YuvStimProducer> findStimProducerByCameraId(
	const std::string& resolvedCameraId);

bool validateAttachRequest(
	const std::shared_ptr<device::DeviceAttachmentSpec>& spec);

sscl::co::ViralNonPostingInvoker<int> lcameraBuff_initializeCInd();
sscl::co::ViralNonPostingInvoker<int> lcameraBuff_finalizeCInd();

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

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

} // namespace smo::stim_buff::lcamera_buff

#endif // LCAMERA_BUFF_INTERNAL_H
