#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)
{}

MctpReactorDevice::MctpReactorDevice(
    const std::shared_ptr<sdbusplus::asio::connection>& connection,
    const std::string& deviceObjectPath, const std::string& endpointPath,
    std::optional<int> busNumber, std::optional<int> address) :
    connection(connection), deviceObjectPath(deviceObjectPath),
    resolvedEndpointPath(endpointPath),
    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)
{
    if (!resolvedEndpointPath.empty())
    {
        finaliseEndpoint(resolvedEndpointPath, std::move(action));
        return;
    }
    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();
    }
}
