#include "MctpReactorDevice.hpp"

#include "MctpEndpoint.hpp"
#include "Utils.hpp"

#include <boost/algorithm/string.hpp>
#include <boost/system/detail/errc.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/message/native_types.hpp>

#include <exception>
#include <limits>
#include <memory>
#include <optional>
#include <string_view>
#include <system_error>
#include <variant>

namespace
{
constexpr const char* objectMapperServiceName =
    "xyz.openbmc_project.ObjectMapper";
constexpr const char* configuresObjectPathSuffix = "/configures";
constexpr const char* dbusPropertiesInterface =
    "org.freedesktop.DBus.Properties";
constexpr const char* associationInterface = "xyz.openbmc_project.Association";
constexpr const char* endpointPropertyName = "endpoints";

// Returns the token after the last '/' character.
std::string extractSuffixFromObjectPath(const std::string& path)
{
    std::vector<std::string> tokens;
    boost::split(tokens, path, boost::is_any_of("/"));
    if (tokens.empty())
    {
        return "";
    }
    return tokens.back();
}

// Returns a pair consisting of the network number and endpoint ID parsed from
// an MCTP endpoint object path such as
// "/au/com/codeconstruct/mctp1/networks/1/endpoints/17" for example.
// Assumes that the last number is EID and the first number is the network.
std::optional<std::pair<int, uint8_t>>
    extractNetworkAndEid(std::string_view endpointObjectPath)
{
    std::vector<std::string> tokens;
    boost::split(tokens, endpointObjectPath, boost::is_any_of("/"));
    auto it = tokens.rbegin();

    // Find EID.
    int eid = -1;
    for (; it != tokens.rend(); ++it)
    {
        try
        {
            eid = std::stoi(*it);
        }
        catch (...)
        {
            continue;
        }
        break;
    }
    // Make sure the next (preceding) token is "enpdoints".
    if (it == tokens.rend() || it + 1 == tokens.rend() ||
        *(it + 1) != "endpoints")
    {
        return std::nullopt;
    }
    // Number validity check.
    if (eid < std::numeric_limits<uint8_t>::min() ||
        eid > std::numeric_limits<uint8_t>::max())
    {
        return std::nullopt;
    }

    // Find network.
    int network = -1;
    for (++it; it != tokens.rend(); ++it)
    {
        try
        {
            network = std::stoi(*it);
        }
        catch (...)
        {
            continue;
        }
        break;
    }
    // Make sure the next (preceding) token is "networks".
    if (it == tokens.rend() || it + 1 == tokens.rend() ||
        *(it + 1) != "networks")
    {
        return std::nullopt;
    }
    // Number validity check.
    if (network < 0)
    {
        return std::nullopt;
    }
    return std::make_pair(network, eid);
}

} // namespace

MctpReactorDevice::MctpReactorDevice(
    const std::shared_ptr<sdbusplus::asio::connection>& connection,
    const std::string& deviceObjectPath, std::optional<int> busNumber,
    std::optional<int> address) :
    connection(connection), deviceObjectPath(deviceObjectPath),
    prettyObjectName(extractSuffixFromObjectPath(deviceObjectPath)),
    isI2cAccessible(busNumber.has_value() && address.has_value()),
    i2cBusNumber(isI2cAccessible ? busNumber.value() : -1),
    i2cAddress(isI2cAccessible ? address.value() : -1)
{}

void MctpReactorDevice::setup(
    std::function<void(const std::error_code& ec,
                       const std::shared_ptr<MctpEndpoint>& ep)>&& action)
{
    auto onGetPropertyReturned =
        [weak{weak_from_this()}, action{std::move(action)}](
            const boost::system::error_code& ec,
            const std::variant<std::vector<std::string>>& value) mutable {
        if (ec)
        {
            action(ec, {});
            return;
        }
        const auto* const endpointObjectPaths =
            std::get_if<std::vector<std::string>>(&value);
        if (!endpointObjectPaths || endpointObjectPaths->size() != 1)
        {
            auto errc = std::errc::invalid_argument;
            auto ec = std::make_error_code(errc);
            action(ec, {});
            return;
        }

        if (auto self = weak.lock())
        {
            self->finaliseEndpoint(endpointObjectPaths->front(),
                                   std::move(action));
        }
    };
    try
    {
        const std::string configuresObjectPath = deviceObjectPath +
                                                 configuresObjectPathSuffix;
        connection->async_method_call(
            onGetPropertyReturned, objectMapperServiceName,
            configuresObjectPath, dbusPropertiesInterface, "Get",
            std::string(associationInterface),
            std::string(endpointPropertyName));
    }
    catch (const sdbusplus::exception::SdBusError& err)
    {
        auto errc = std::errc::no_such_device_or_address;
        auto ec = std::make_error_code(errc);
        action(ec, {});
    }
}

void MctpReactorDevice::remove()
{
    if (endpoint)
    {
        endpoint->remove();
    }
}

std::string MctpReactorDevice::describe() const
{
    return "MctpReactorDev: " + prettyObjectName;
}

void MctpReactorDevice::onEndpointInterfacesRemoved(
    const std::weak_ptr<MctpReactorDevice>& weak,
    const std::string& endpointObjectPath, sdbusplus::message_t& msg)
{
    auto objectPath = msg.unpack<sdbusplus::message::object_path>();
    if (objectPath.str != endpointObjectPath)
    {
        return;
    }

    auto removedInterfaces = msg.unpack<std::set<std::string>>();
    if (!removedInterfaces.contains(mctpdEndpointControlInterface))
    {
        return;
    }

    if (auto self = weak.lock())
    {
        self->endpointRemoved();
    }
}

void MctpReactorDevice::finaliseEndpoint(
    const std::string& endpointObjectPath,
    std::function<void(const std::error_code& ec,
                       const std::shared_ptr<MctpEndpoint>& ep)>&& action)
{
    const auto matchSpec =
        std::string(sdbusplus::bus::match::rules::interfacesRemoved())
            .append(
                sdbusplus::bus::match::rules::argNpath(0, endpointObjectPath));
    removeMatch = std::make_unique<sdbusplus::bus::match_t>(
        *connection, matchSpec,
        std::bind_front(MctpReactorDevice::onEndpointInterfacesRemoved,
                        weak_from_this(), endpointObjectPath));

    const auto networkAndEid = extractNetworkAndEid(endpointObjectPath);
    if (!networkAndEid)
    {
        action(std::make_error_code(std::errc::invalid_argument), nullptr);
        return;
    }
    const auto [network, eid] = networkAndEid.value();
    endpoint = std::make_shared<MctpdEndpoint>(shared_from_this(), connection,
                                               endpointObjectPath, network, eid,
                                               isI2cAccessible);
    action({}, endpoint);
}

void MctpReactorDevice::endpointRemoved()
{
    if (endpoint)
    {
        removeMatch.reset();
        endpoint->remove();
        endpoint.reset();
    }
}
