#include <gtest/gtest.h>
#include "config.h"
#include "EOSio.h"
#include "helm.h"
#include "resourceManager.h"
#include "resourceManagerTypes.h"

#include <string>
#include <stdexcept>
#include <vector>
#include <set>

#include "debug.h"

/**
 * @file configTest.cpp
 * @brief Unit tests for the resourceManager class.
 */


std::string TEST_CONFIG = std::string(getenv("MESON_SOURCE_ROOT")) + "/tests/testsConfig.yaml";
/**
 * @brief Test suite for the resourceManager class.
 */
class resourceManagerTest : public ::testing::Test {};

/**
 * @brief Test the constructor of the resourceManager class.
 */
TEST_F(resourceManagerTest, constructor) {
    serif::config::Config::getInstance().loadConfig(TEST_CONFIG);
    EXPECT_NO_THROW(serif::resource::ResourceManager::getInstance());
}

TEST_F(resourceManagerTest, getAvaliableResources) {
    serif::config::Config::getInstance().loadConfig(TEST_CONFIG);
    serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance();
    std::vector<std::string> resources = rm.getAvailableResources();
    std::set<std::string> expected = {"eos:helm", "mesh:polySphere"};
    std::set<std::string> actual(resources.begin(), resources.end());
    EXPECT_EQ(expected, actual);
}

TEST_F(resourceManagerTest, getResource) {
    serif::config::Config::getInstance().loadConfig(TEST_CONFIG);
    serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance();
    std::string name = "eos:helm";
    const serif::resource::types::Resource &r = rm.getResource(name);
    // BREAKPOINT();
    const auto &eos = std::get<std::unique_ptr<serif::eos::EOSio>>(r);
    EXPECT_EQ("helm", eos->getFormat());
    serif::eos::EOSTable &table = eos->getTable();

    // -- Extract the Helm table from the EOSTable
    serif::eos::helmholtz::HELMTable &helmTable = *std::get<std::unique_ptr<serif::eos::helmholtz::HELMTable>>(table);
    EXPECT_DOUBLE_EQ(helmTable.f[0][0], -1692098915534.8142);

    EXPECT_THROW(rm.getResource("opac:GS98:high:doesNotExist"), std::runtime_error);
}


