#ifndef SENSE_API_MANAGER_H
#define SENSE_API_MANAGER_H

#include <config.h>
#include <memory>
#include <vector>
#include <string>
#include <optional>
#include <functional>
#include <spinscale/asynchronousLoop.h>
#include <stimBuffApis/stimBuffApiLib.h>
#include <user/deviceAttachmentSpec.h>
#include <spinscale/callback.h>
#include <spinscale/qutex.h>

namespace smo {
namespace stim_buff {

class StimBuffApiManager
{
public:
	static StimBuffApiManager& getInstance()
	{
		static StimBuffApiManager instance;
		return instance;
	}

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

	StimBuffApiLib& loadStimBuffApiLib(
		const std::string& libraryPath,
		const std::shared_ptr<sscl::ComponentThread>& componentThread);

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

	void initializeStimBuffApiLib(StimBuffApiLib& lib);
	void finalizeStimBuffApiLib(StimBuffApiLib& lib);

	void loadAllStimBuffApiLibsFromOptions(
		const std::shared_ptr<sscl::ComponentThread>& componentThread);

	void unloadAllStimBuffApiLibs(void);
	void initializeAllStimBuffApiLibs(void);
	void finalizeAllStimBuffApiLibs(void);

	std::string stringifyLibs() const;

private:
	StimBuffApiManager()
	: qutex("StimBuffApiManager")
	{}
	~StimBuffApiManager() = default;

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

	std::vector<std::shared_ptr<StimBuffApiLib>> stimBuffApiLibs;

public:
	sscl::Qutex qutex;

public:
	static std::optional<std::string> searchForLibInSmoSearchPaths(
		const std::string& libraryPath);
};

} // namespace stim_buff
} // namespace smo

#endif // SENSE_API_MANAGER_H
