#ifndef COMPARATOR_API_MANAGER_H
#define COMPARATOR_API_MANAGER_H

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
#include <user/comparator.h>
#include <user/comparatorApiDesc.h>
#include <comparatorLibs/comparatorLib.h>
#include <spinscale/co/coQutex.h>
#include <spinscale/sharedResourceGroup.h>

namespace smo {
namespace comparator_lib {

class ComparatorApiManager
{
public:
	struct Resources
	{
		std::vector<std::shared_ptr<ComparatorLib>> libs;
		std::unordered_map<
			uint64_t, std::shared_ptr<cologex::ExportedComparatorTypeDesc>>
			typeRegistry;
	};

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

	ComparatorLib& loadComparatorLib(const std::string& libraryPath);

	void unloadComparatorLib(const std::string& libraryPath);

	void unloadAllComparatorLibs(void);

	void loadAllComparatorApiLibsFromOptions(void);

	std::optional<std::shared_ptr<ComparatorLib>> getComparatorLib(
		const std::string& libraryPath);

	std::shared_ptr<cologex::ExportedComparatorTypeDesc> getComparatorType(
		cologex::ComparatorTypeId typeId);

	std::unique_ptr<cologex::Comparator> getNewComparatorInstance(
		cologex::ComparatorTypeId typeId);

	std::unique_ptr<cologex::Comparator> getNewComparatorInstance(
		const std::shared_ptr<cologex::ExportedComparatorTypeDesc>&
			comparatorType);

	std::string stringifyLibs() const;

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

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

	~ComparatorApiManager() = default;

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

} // namespace comparator_lib
} // namespace smo

#endif // COMPARATOR_API_MANAGER_H
