#include "association_manager.hpp"

#include <phosphor-logging/lg2.hpp>

#include <filesystem>
#include <fstream>

namespace phosphor
{
namespace inventory
{
namespace manager
{
namespace associations
{
namespace fs = std::filesystem;

Manager::Manager(sdbusplus::bus_t& bus, const std::string& jsonPath) :
    _bus(bus), _jsonFile(jsonPath)
{
    // If there aren't any conditional associations files, look for
    // that default nonconditional one.
    if (!loadConditions())
    {
        if (fs::exists(_jsonFile))
        {
            std::ifstream file{_jsonFile};
            auto json = nlohmann::json::parse(file, nullptr, true);
            load(json);
        }
    }
}

/**
 * @brief Throws an exception if 'num' is zero. Used for JSON
 *        sanity checking.
 *
 * @param[in] num - the number to check
 */
void throwIfZero(int num)
{
    if (!num)
    {
        throw std::invalid_argument("Invalid empty field in JSON");
    }
}

bool Manager::loadConditions()
{
    auto dir = _jsonFile.parent_path();

    for (const auto& dirent : fs::recursive_directory_iterator(dir))
    {
        const auto& path = dirent.path();
        if (path.extension() == ".json")
        {
            std::ifstream file{path};
            auto json = nlohmann::json::parse(file, nullptr, true);

            if (json.is_object() && json.contains("condition"))
            {
                const auto& conditionJSON = json.at("condition");
                if (!conditionJSON.contains("path") ||
                    !conditionJSON.contains("interface") ||
                    !conditionJSON.contains("property") ||
                    !conditionJSON.contains("values"))
                {
                    lg2::error(
                        "Invalid JSON in associations condition entry in {PATH}. Skipping file.",
                        "PATH", path);
                    continue;
                }

                Condition c;
                c.file = path;
                c.path = conditionJSON["path"].get<std::string>();
                if (c.path.front() != '/')
                {
                    c.path = '/' + c.path;
                }
                fprintf(stderr, "found conditions file %s\n", c.file.c_str());
                c.interface = conditionJSON["interface"].get<std::string>();
                c.property = conditionJSON["property"].get<std::string>();

                // The values are in an array, and need to be
                // converted to an InterfaceVariantType.
                for (const auto& value : conditionJSON["values"])
                {
                    if (value.is_array())
                    {
                        std::vector<uint8_t> variantValue;
                        for (const auto& v : value)
                        {
                            variantValue.push_back(v.get<uint8_t>());
                        }
                        c.values.push_back(variantValue);
                        continue;
                    }

                    // Try the remaining types
                    auto s = value.get_ptr<const std::string*>();
                    auto i = value.get_ptr<const int64_t*>();
                    auto b = value.get_ptr<const bool*>();
                    if (s)
                    {
                        c.values.push_back(*s);
                    }
                    else if (i)
                    {
                        c.values.push_back(*i);
                    }
                    else if (b)
                    {
                        c.values.push_back(*b);
                    }
                    else
                    {
                        lg2::error(
                            "Invalid condition property value in {FILE}:",
                            "FILE", c.file);
                        throw std::runtime_error(
                            "Invalid condition property value");
                    }
                }

                _conditions.push_back(std::move(c));
            }
        }
    }

    return !_conditions.empty();
}

bool Manager::conditionMatch(const sdbusplus::message::object_path& objectPath,
                             const Object& object)
{
    fs::path foundPath;
    for (const auto& condition : _conditions)
    {
        if (condition.path != objectPath)
        {
            continue;
        }

        auto interface = std::find_if(
            object.begin(), object.end(), [&condition](const auto& i) {
                return i.first == condition.interface;
            });
        if (interface == object.end())
        {
            continue;
        }

        auto property =
            std::find_if(interface->second.begin(), interface->second.end(),
                         [&condition](const auto& p) {
                             return condition.property == p.first;
                         });
        if (property == interface->second.end())
        {
            continue;
        }

        auto match = std::find(condition.values.begin(), condition.values.end(),
                               property->second);
        if (match != condition.values.end())
        {
            foundPath = condition.file;
            break;
        }
    }

    if (!foundPath.empty())
    {
        std::ifstream file{foundPath};
        auto json = nlohmann::json::parse(file, nullptr, true);
        load(json["associations"]);
        _conditions.clear();
        return true;
    }

    return false;
}

bool Manager::conditionMatch()
{
    fs::path foundPath;

    for (const auto& condition : _conditions)
    {
        // Compare the actualValue field against the values in the
        // values vector to see if there is a condition match.
        auto found = std::find(condition.values.begin(), condition.values.end(),
                               condition.actualValue);
        if (found != condition.values.end())
        {
            foundPath = condition.file;
            break;
        }
    }

    if (!foundPath.empty())
    {
        std::ifstream file{foundPath};
        auto json = nlohmann::json::parse(file, nullptr, true);
        load(json["associations"]);
        _conditions.clear();
        return true;
    }

    return false;
}

void Manager::load(const nlohmann::json& json)
{
    const std::string root{INVENTORY_ROOT};

    for (const auto& jsonAssoc : json)
    {
        // Only add the slash if necessary
        std::string path = jsonAssoc.at("path");
        throwIfZero(path.size());
        if (path.front() != '/')
        {
            path = root + "/" + path;
        }
        else
        {
            path = root + path;
        }

        auto& assocEndpoints = _associations[path];

        for (const auto& endpoint : jsonAssoc.at("endpoints"))
        {
            std::string ftype = endpoint.at("types").at("fType");
            std::string rtype = endpoint.at("types").at("rType");
            throwIfZero(ftype.size());
            throwIfZero(rtype.size());
            Types types{std::move(ftype), std::move(rtype)};

            Paths paths = endpoint.at("paths");
            throwIfZero(paths.size());
            assocEndpoints.emplace_back(std::move(types), std::move(paths));
        }
    }
}

void Manager::createAssociations(const std::string& objectPath,
                                 bool deferSignal)
{
    auto endpoints = _associations.find(objectPath);
    if (endpoints == _associations.end())
    {
        return;
    }

    if (std::find(_handled.begin(), _handled.end(), objectPath) !=
        _handled.end())
    {
        return;
    }

    _handled.push_back(objectPath);

    for (const auto& endpoint : endpoints->second)
    {
        const auto& types = std::get<typesPos>(endpoint);
        const auto& paths = std::get<pathsPos>(endpoint);

        for (const auto& endpointPath : paths)
        {
            const auto& forwardType = std::get<forwardTypePos>(types);
            const auto& reverseType = std::get<reverseTypePos>(types);

            createAssociation(objectPath, forwardType, endpointPath,
                              reverseType, deferSignal);
        }
    }
}

void Manager::createAssociation(
    const std::string& forwardPath, const std::string& forwardType,
    const std::string& reversePath, const std::string& reverseType,
    bool deferSignal)
{
    auto object = _associationIfaces.find(forwardPath);
    if (object == _associationIfaces.end())
    {
        auto a = std::make_unique<AssociationObject>(
            _bus, forwardPath.c_str(), AssociationObject::action::defer_emit);

        using AssociationProperty =
            std::vector<std::tuple<std::string, std::string, std::string>>;
        AssociationProperty prop;

        prop.emplace_back(forwardType, reverseType, reversePath);
        a->associations(std::move(prop));
        if (!deferSignal)
        {
            a->emit_object_added();
        }
        _associationIfaces.emplace(forwardPath, std::move(a));
    }
    else
    {
        // Interface exists, just update the property
        auto prop = object->second->associations();
        prop.emplace_back(forwardType, reverseType, reversePath);
        object->second->associations(std::move(prop), deferSignal);
    }
}
} // namespace associations
} // namespace manager
} // namespace inventory
} // namespace phosphor
