#include "topology.hpp"

#include "phosphor-logging/lg2.hpp"

const AssocName assocContaining =
    AssocName("containing", "contained_by", {"Chassis"},
              {"Board", "Chassis", "PowerSupply"});
const AssocName assocContainedBy = assocContaining.getReverse();

// Topology tests say that a chassis can be powering another chassis.
// In case there is any confusion as to why 'Chassis' can have 'powering'
// association.
const AssocName assocPowering =
    AssocName("powering", "powered_by", {"Chassis", "PowerSupply"},
              {"Board", "Chassis", "PowerSupply"});
const AssocName assocPoweredBy = assocPowering.getReverse();

const std::vector<AssocName> supportedAssocs = {
    assocContaining,
    assocContainedBy,
    assocPowering,
    assocPoweredBy,
};

AssocName::AssocName(const std::string& name, const std::string& reverse,
                     const std::set<std::string>& allowedOnBoardTypes,
                     const std::set<std::string>& allowedOnBoardTypesReverse) :
    name(name), reverse(reverse), allowedOnBoardTypes(allowedOnBoardTypes),
    allowedOnBoardTypesReverse(allowedOnBoardTypesReverse)
{}

AssocName AssocName::getReverse() const
{
    return {reverse, name, allowedOnBoardTypesReverse, allowedOnBoardTypes};
}

bool AssocName::operator<(const AssocName& other) const
{
    return name < other.name;
}

std::optional<AssocName> Topology::getAssocByName(const std::string& name)
{
    for (const auto& assoc : supportedAssocs)
    {
        if (assoc.name == name)
        {
            return assoc;
        }
    }
    return std::nullopt;
}

void Topology::addBoard(const std::string& path, const std::string& boardType,
                        const std::string& boardName,
                        const nlohmann::json& exposesItem)
{
    auto findType = exposesItem.find("Type");
    if (findType == exposesItem.end())
    {
        return;
    }

    boardNames.try_emplace(boardName, path);

    PortType exposesType = findType->get<std::string>();

    if (exposesType == "DownstreamPort")
    {
        addDownstreamPort(path, exposesItem);
    }
    else if (exposesType == "Port")
    {
        addConfiguredPort(path, exposesItem);
    }
    else if (exposesType.ends_with("Port"))
    {
        addPort(exposesType, path, assocContaining);
    }
    else
    {
        return;
    }
    boardTypes[path] = boardType;
}

void Topology::addConfiguredPort(const Path& path,
                                 const nlohmann::json& exposesItem)
{
    const auto findConnectsToName = exposesItem.find("Name");
    if (findConnectsToName == exposesItem.end())
    {
        lg2::error("Board at path {PATH} is missing 'Name'", "PATH", path);
        return;
    }
    const std::string connectsToName = findConnectsToName->get<std::string>();

    const auto findPortType = exposesItem.find("PortType");
    if (findPortType == exposesItem.end())
    {
        lg2::error("Board at path {PATH} is missing PortType", "PATH", path);
        return;
    }
    const std::string portType = findPortType->get<std::string>();

    const auto assoc = getAssocByName(portType);
    if (!assoc.has_value())
    {
        lg2::error("Could not find configured association name {ASSOC}",
                   "ASSOC", portType);
        return;
    }

    addPort(connectsToName, path, assoc.value());
}

void Topology::addDownstreamPort(const Path& path,
                                 const nlohmann::json& exposesItem)
{
    auto findConnectsTo = exposesItem.find("ConnectsToType");
    if (findConnectsTo == exposesItem.end())
    {
        lg2::error("Board at path {PATH} is missing ConnectsToType", "PATH",
                   path);
        return;
    }
    PortType connectsTo = findConnectsTo->get<std::string>();

    addPort(connectsTo, path, assocContainedBy);

    auto findPoweredBy = exposesItem.find("PowerPort");
    if (findPoweredBy != exposesItem.end())
    {
        addPort(connectsTo, path, assocPowering);
    }
}

void Topology::addPort(const PortType& port, const Path& path,
                       const AssocName& assocName)
{
    if (!ports.contains(port))
    {
        ports.insert({port, {}});
    }
    if (!ports[port].contains(path))
    {
        ports[port].insert({path, {}});
    }
    ports[port][path].insert(assocName);
}

std::unordered_map<std::string, std::set<Association>> Topology::getAssocs(
    BoardPathsView boardPaths)
{
    std::unordered_map<std::string, std::set<Association>> result;

    // look at each upstream port type
    for (const auto& port : ports)
    {
        fillAssocsForPortId(result, boardPaths, port.second);
    }
    return result;
}

void Topology::fillAssocsForPortId(
    std::unordered_map<std::string, std::set<Association>>& result,
    BoardPathsView boardPaths,
    const std::map<Path, std::set<AssocName>>& pathAssocs)
{
    for (const auto& member : pathAssocs)
    {
        for (const auto& other : pathAssocs)
        {
            if (other.first == member.first)
            {
                continue;
            }
            for (const auto& assocName : member.second)
            {
                // if the other end of the assocation does not declare
                // the reverse association, do not associate
                const bool otherAgrees =
                    other.second.contains(assocName.getReverse());

                // quirk: since the other side of the association cannot declare
                // to be powered_by in the legacy schema, in case of "powering",
                // the two associations do not have to agree.
                if (!otherAgrees && assocName != assocPowering)
                {
                    continue;
                }

                fillAssocForPortId(result, boardPaths, member.first,
                                   other.first, assocName);
            }
        }
    }
}

void Topology::fillAssocForPortId(
    std::unordered_map<std::string, std::set<Association>>& result,
    BoardPathsView boardPaths, const Path& upstream, const Path& downstream,
    const AssocName& assocName)
{
    if (!assocName.allowedOnBoardTypes.contains(boardTypes[upstream]))
    {
        lg2::error(
            "Cannot create Association Definition {ASSOC} for {PATH} with board type {TYPE}",
            "ASSOC", assocName.name, "PATH", upstream, "TYPE",
            boardTypes[upstream]);
        return;
    }
    // The downstream path must be one we care about.
    if (!std::ranges::contains(boardPaths, upstream))
    {
        return;
    }

    // quirk: legacy code did not associate from both sides
    // TODO(alexander): revisit this
    if (assocName == assocContaining || assocName == assocPoweredBy)
    {
        return;
    }

    result[upstream].insert({assocName.name, assocName.reverse, downstream});
}

void Topology::remove(const std::string& boardName)
{
    // Remove the board from boardNames, and then using the path
    // found in boardNames remove it from ports
    auto boardFind = boardNames.find(boardName);
    if (boardFind == boardNames.end())
    {
        return;
    }

    std::string boardPath = boardFind->second;

    boardNames.erase(boardFind);

    for (auto& port : ports)
    {
        port.second.erase(boardPath);
    }
}
