#ifndef SENSE_API_MANAGER_H
#define SENSE_API_MANAGER_H

#include <config.h>
#include <memory>
#include <vector>
#include <string>
#include <optional>
#include <functional>
#include <stimBuffApis/stimBuffApiLib.h>
#include <user/deviceAttachmentSpec.h>
#include <body/bodyThread.h>
#include <spinscale/co/coQutex.h>
#include <spinscale/sharedResourceGroup.h>

namespace smo {
namespace stim_buff {

class StimBuffApiManager
{
public:
	struct Resources
	{
		std::vector<std::shared_ptr<StimBuffApiLib>> libs;
	};

	static StimBuffApiManager& getInstance()
	{
		static StimBuffApiManager instance;
		return instance;
	}

	void initialize(void)
	{};
	void finalize(void)
	{};

	StimBuffApiLib& loadStimBuffApiLib(const std::string& libraryPath);

	std::optional<std::shared_ptr<StimBuffApiLib>> findStimBuffApiLibByLibraryPath(
		const std::string& libraryPath);
	std::optional<std::shared_ptr<StimBuffApiLib>> findStimBuffApiLibByApiName(
		const std::string& apiName);
	StimBuffApiLib &getStimBuffApiLibByApiName(const std::string& apiName);
	void unloadStimBuffApiLib(const std::string& libraryPath);

	void loadAllStimBuffApiLibsFromOptions(void);
	void unloadAllStimBuffApiLibs(void);

	body::BodyViralPostingInvoker<void> initializeStimBuffApiLibCReq(
		StimBuffApiLib &lib, bool acquireListLock=true);
	body::BodyViralPostingInvoker<void> finalizeStimBuffApiLibCReq(
		StimBuffApiLib &lib, bool acquireListLock=true);

	body::BodyViralPostingInvoker<void> initializeAllStimBuffApiLibsCReq();
	body::BodyViralPostingInvoker<void> finalizeAllStimBuffApiLibsCReq();

	std::string stringifyLibs() const;

public:
	sscl::SharedResourceGroup<sscl::co::CoQutex, Resources> s;

private:
	StimBuffApiManager()
	: s("StimBuffApiManager")
	{}

	~StimBuffApiManager() = default;

	StimBuffApiManager(const StimBuffApiManager&) = delete;
	StimBuffApiManager& operator=(const StimBuffApiManager&) = delete;
};

} // namespace stim_buff
} // namespace smo

#endif // SENSE_API_MANAGER_H
