#ifndef MINORI_CORE_JSON_H_
#define MINORI_CORE_JSON_H_

#include "json/json.hpp"

#include <optional>

namespace nlohmann {

/* hack to get std::optional working */
template<typename T>
void to_json(nlohmann::json &j, const std::optional<T> &v)
{
	if (v.has_value())
		j = v.value();
	else
		j = nullptr;
}

template<typename T>
void from_json(const nlohmann::json &j, std::optional<T> &v)
{
	v = j.is_null() ? std::nullopt : j.get<T>();
}

} // namespace nlohmann

namespace JSON {

template<typename T = std::string>
T GetString(const nlohmann::json &json, const nlohmann::json::json_pointer &ptr, T def)
{
	if (json.contains(ptr) && json[ptr].is_string())
		return json[ptr].get<T>();
	else
		return def;
}

template<typename T = int>
T GetNumber(const nlohmann::json &json, const nlohmann::json::json_pointer &ptr, T def = 0)
{
	if (json.contains(ptr) && json[ptr].is_number())
		return json[ptr].get<T>();
	else
		return def;
}

template<typename T = std::vector<std::string>>
T GetArray(const nlohmann::json &json, const nlohmann::json::json_pointer &ptr, T def = 0)
{
	if (json.contains(ptr) && json[ptr].is_array())
		return json[ptr].get<T>();
	else
		return def;
}

nlohmann::json GetValue(const nlohmann::json &json, const nlohmann::json::json_pointer &ptr);
bool GetBoolean(const nlohmann::json &json, const nlohmann::json::json_pointer &ptr, bool def = false);

} // namespace JSON

#endif // MINORI_CORE_JSON_H_