/** Node list
 *
 * @author Steffen Vogel <post@steffenvogel.de>
 * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
 * @license Apache 2.0
 **********************************************************************************/


#include <villas/node_list.hpp>
#include <villas/node.hpp>
#include <villas/exceptions.hpp>

using namespace villas;
using namespace villas::node;

Node * NodeList::lookup(const uuid_t &uuid)
{
	for (auto *n : *this) {
		if (!uuid_compare(uuid, n->getUuid()))
			return n;
	}

	return nullptr;
}

Node * NodeList::lookup(const std::string &name)
{
	for (auto *n : *this) {
		if (name == n->getNameShort())
			return n;
	}

	return nullptr;
}

int NodeList::parse(json_t *json, NodeList &all)
{
	Node *node;
	const char *str;

	size_t index;
	json_t *elm;

	auto logger = logging.get("node");

	switch (json_typeof(json)) {
		case JSON_STRING:
			str = json_string_value(json);
			node = all.lookup(str);
			if (!node)
				goto invalid2;

			push_back(node);
			break;

		case JSON_ARRAY:
			json_array_foreach(json, index, elm) {
				if (!json_is_string(elm))
					goto invalid;

				str = json_string_value(elm);
				node = all.lookup(str);
				if (!node)
					goto invalid;

				push_back(node);
			}
			break;

		default:
			goto invalid;
	}

	return 0;

invalid:
	throw RuntimeError("The node list must be an a single or an array of strings referring to the keys of the 'nodes' section");

	return -1;

invalid2:
	std::stringstream allss;
	for (auto *n : all)
		allss << " " << n->getNameShort();

	throw RuntimeError("Unknown node {}. Choose of one of:{}", str, allss.str());

	return 0;
}

json_t * NodeList::toJson() const
{
	json_t *json_nodes = json_array();

	for (const auto *n : *this)
		json_array_append_new(json_nodes, n->toJson());

	return json_nodes;
}