#include "GnsServer.hpp"

#include <cpr/cpr.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;


namespace gns {


GnsServer::GnsServer(const std::string& host, const std::uint16_t port) {
    this->host = host;
    this->port = port;
}

std::string GnsServer::getApiBase() const {
    return "http://" + this->host + ":" + std::to_string(this->port) + "/v2/";
}

std::vector<std::shared_ptr<GnsProject>> GnsServer::getProjects() const {
    std::vector<std::shared_ptr<GnsProject>> projects;

    // request the API endpoint
    cpr::Url endpoint = this->getApiBase() + "projects";
    cpr::Response response = Get(endpoint);

    // check for a valid response
    if (response.error.code != cpr::ErrorCode::OK)
        throw std::runtime_error(response.error.message);

    // check for valid content
    if (response.header["Content-Type"] != "application/json")
        throw std::runtime_error("Data must be JSON formatted.");

    // parse the data
    json data = json::parse(response.text);

    // deserialize the projects
    projects.reserve(data.size());
    for (const auto& project_data : data)
        projects.emplace_back(std::make_shared<GnsProject>(
            this,
            project_data["project_id"]
        ));

    return projects;
}

std::vector<std::shared_ptr<GnsNode>> GnsServer::getNodes() const {
    std::vector<std::shared_ptr<GnsNode>> nodes;

    // get all the nodes from all the projects
    for (const std::shared_ptr<GnsProject>& project : this->getProjects()) {
        std::vector<std::shared_ptr<GnsNode>> project_nodes = project->getNodes();
        nodes.insert(nodes.end(), project_nodes.begin(), project_nodes.end());
    }

    return nodes;
}


}