#include "GnsProject.hpp"
#include "GnsServer.hpp"
#include "GnsPort.hpp"

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


namespace gns {


GnsProject::GnsProject(const GnsServer* server, std::string uuid) {
    this->server = server;
    this->uuid = std::move(uuid);
}

std::string GnsProject::getApiBase() const {
    return this->server->getApiBase() + "projects/" + this->uuid + "/";
}

std::string GnsProject::getUuid() const {
    return this->uuid;
}

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

    // request the API endpoint
    cpr::Url endpoint = this->getApiBase() + "nodes";
    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
    nodes.reserve(data.size());
    for (const auto& node_data : data) {
        // parse the ports of the node
        std::vector<json> ports_data = node_data.value("ports", std::vector<json>{});
        std::vector<GnsPort> ports;
        ports.reserve(ports_data.size());
        for (const auto& port_data : ports_data) {
            // get the mac of the port
            std::optional<std::string> mac_address;
            if (port_data.contains("mac_address"))
                mac_address.emplace(port_data["mac_address"]);

            // save the port data
            ports.emplace_back(mac_address);
        }

        // save the node
        nodes.emplace_back(
            this,
            node_data["node_id"],
            ports
        );
    }

    return nodes;
}



}