#include <boostAsioLinkageFix.h>

#include <lcameraDev.h>
#include <probeRunner.h>
#include <iostream>
#include <spinscale/co/nonViralTaskNursery.h>
#include <string>

namespace {

sscl::co::NonViralNonPostingInvoker probeSelectorCInd(
	std::exception_ptr& exceptionStorage,
	std::function<void()> callerLambda,
	const std::string& deviceSelector)
{
	(void)exceptionStorage;
	(void)callerLambda;

	const lcamera_dev::LcameraDevGetOrCreateResult createResult =
		co_await lcameraDev_getOrCreateDeviceCReq(deviceSelector);

	std::cout << "lcameraDev_probe: opened session for camera id="
		<< createResult.resolvedIdentity.id << '\n';

	co_await lcameraDev_releaseDeviceCReq(createResult.deviceSession);

	std::cout << "lcameraDev_probe: released session\n";
	co_return;
}

void runProbe(
	const std::shared_ptr<sscl::ComponentThread>& componentThread,
	const std::string& deviceSelector)
{
	lcameraDev_main(componentThread);

	sscl::co::NonViralTaskNursery nursery;
	nursery.openAdmission();
	nursery.launch(
		[deviceSelector](sscl::co::NonViralTaskNursery::Slot::Lease& lease)
		{
			return probeSelectorCInd(
				lease.getExceptionStorage(),
				lease.getCallerLambda(),
				deviceSelector);
		});
	nursery.closeAdmission();
	nursery.syncAwaitAllSettlements(componentThread->getIoContext());

	lcameraDev_exit();
}

} // namespace

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::cerr << "Usage: lcameraDev_probe <deviceSelector>\n";
		return 1;
	}

	try {
		const std::string deviceSelector = argv[1];

		lcamera_dev_probe::runOnComponentThread(
			[&](const std::shared_ptr<sscl::ComponentThread>& componentThread)
			{
				runProbe(componentThread, deviceSelector);
			});

		return 0;
	}
	catch (const std::exception& exc) {
		std::cerr << "lcameraDev_probe: " << exc.what() << '\n';
		return 1;
	}
}
