#include "configuration.hpp"

#include "perform_probe.hpp"
#include "utils.hpp"

#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>
#include <valijson/adapters/nlohmann_json_adapter.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validator.hpp>

#include <filesystem>
#include <fstream>
#include <string>
#include <vector>

Configuration::Configuration()
{
    loadConfigurations();
    filterProbeInterfaces();
}

void Configuration::loadConfigurations()
{
    const auto start = std::chrono::steady_clock::now();

    // find configuration files
    std::vector<std::filesystem::path> jsonPaths;
    if (!findFiles(
            std::vector<std::filesystem::path>{configurationDirectory,
                                               hostConfigurationDirectory},
            R"(.*\.json)", jsonPaths))
    {
        lg2::error("Unable to find any configuration files in {DIR}", "DIR",
                   configurationDirectory);
        return;
    }

    std::ifstream schemaStream(
        std::string(schemaDirectory) + "/" + globalSchema);
    if (!schemaStream.good())
    {
        lg2::error("Cannot open schema file,  cannot validate JSON, exiting");
        std::exit(EXIT_FAILURE);
        return;
    }
    nlohmann::json schema =
        nlohmann::json::parse(schemaStream, nullptr, false, true);
    if (schema.is_discarded())
    {
        lg2::error(
            "Illegal schema file detected, cannot validate JSON, exiting");
        std::exit(EXIT_FAILURE);
        return;
    }

    for (auto& jsonPath : jsonPaths)
    {
        std::ifstream jsonStream(jsonPath.c_str());
        if (!jsonStream.good())
        {
            lg2::error("unable to open {PATH}", "PATH", jsonPath.string());
            continue;
        }
        auto data = nlohmann::json::parse(jsonStream, nullptr, false, true);
        if (data.is_discarded())
        {
            lg2::error("syntax error in {PATH}", "PATH", jsonPath.string());
            continue;
        }

        if (ENABLE_RUNTIME_VALIDATE_JSON && !validateJson(schema, data))
        {
            lg2::error("Error validating {PATH}", "PATH", jsonPath.string());
            continue;
        }

        if (data.type() == nlohmann::json::value_t::array)
        {
            for (auto& d : data)
            {
                configurations.emplace_back(d);
            }
        }
        else
        {
            configurations.emplace_back(data);
        }
    }

    const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
                              std::chrono::steady_clock::now() - start)
                              .count();

    lg2::debug("Finished loading json configuration in {MILLIS}ms", "MILLIS",
               duration);
}

// Iterate over new configuration and erase items from old configuration.
void deriveNewConfiguration(const nlohmann::json& oldConfiguration,
                            nlohmann::json& newConfiguration)
{
    for (auto it = newConfiguration.begin(); it != newConfiguration.end();)
    {
        auto findKey = oldConfiguration.find(it.key());
        if (findKey != oldConfiguration.end())
        {
            it = newConfiguration.erase(it);
        }
        else
        {
            it++;
        }
    }
}

// validates a given input(configuration) with a given json schema file.
bool validateJson(const nlohmann::json& schemaFile, const nlohmann::json& input)
{
    valijson::Schema schema;
    valijson::SchemaParser parser;
    valijson::adapters::NlohmannJsonAdapter schemaAdapter(schemaFile);
    parser.populateSchema(schemaAdapter, schema);
    valijson::Validator validator;
    valijson::adapters::NlohmannJsonAdapter targetAdapter(input);
    return validator.validate(schema, targetAdapter, nullptr);
}

// Extract the D-Bus interfaces to probe from the JSON config files.
void Configuration::filterProbeInterfaces()
{
    for (auto it = configurations.begin(); it != configurations.end();)
    {
        auto findProbe = it->find("Probe");
        if (findProbe == it->end())
        {
            lg2::error("configuration file missing probe: {PROBE}", "PROBE",
                       *it);
            it++;
            continue;
        }

        nlohmann::json probeCommand;
        if ((*findProbe).type() != nlohmann::json::value_t::array)
        {
            probeCommand = nlohmann::json::array();
            probeCommand.push_back(*findProbe);
        }
        else
        {
            probeCommand = *findProbe;
        }

        for (const nlohmann::json& probeJson : probeCommand)
        {
            const std::string* probe = probeJson.get_ptr<const std::string*>();
            if (probe == nullptr)
            {
                lg2::error("Probe statement wasn't a string, can't parse");
                continue;
            }
            // Skip it if the probe cmd doesn't contain an interface.
            if (probe::findProbeType(*probe))
            {
                continue;
            }

            // syntax requires probe before first open brace
            auto findStart = probe->find('(');
            if (findStart != std::string::npos)
            {
                std::string interface = probe->substr(0, findStart);
                probeInterfaces.emplace(interface);
            }
        }
        it++;
    }
}

bool writeJsonFiles(const nlohmann::json& systemConfiguration)
{
    if (!EM_CACHE_CONFIGURATION)
    {
        return true;
    }

    std::error_code ec;
    std::filesystem::create_directory(configurationOutDir, ec);
    if (ec)
    {
        return false;
    }
    std::ofstream output(currentConfiguration);
    if (!output.good())
    {
        return false;
    }
    output << systemConfiguration.dump(4);
    output.close();
    return true;
}
