#include <cstdio>
#include <cstring>
#include <host-ipmid/oemrouter.hpp>
#include <map>
#include <utility>

namespace oem
{

using Key = std::pair<Number, ipmi_cmd_t>;

// Private implementation of OemRouter Interface.
class RouterImpl : public Router
{
  public:
    RouterImpl()
    {
    }

    // Implement OemRouter Interface.
    void activate() override;
    void registerHandler(Number oen, ipmi_cmd_t cmd, Handler handler) override;

    // Actual message routing function.
    ipmi_ret_t routeMsg(ipmi_cmd_t cmd, const uint8_t* reqBuf,
                        uint8_t* replyBuf, size_t* dataLen);

  private:
    std::map<Key, Handler> handlers;
};

// Static global instance for simplicity.
static RouterImpl* globalRouterImpl;

// TODO Refactor ipmid to avoid need for singleton here.
Router* mutableRouter()
{
    if (!globalRouterImpl)
    {
        globalRouterImpl = new RouterImpl;
    }
    return globalRouterImpl;
}

ipmi_ret_t RouterImpl::routeMsg(ipmi_cmd_t cmd, const uint8_t* reqBuf,
                                uint8_t* replyBuf, size_t* dataLen)
{
    // Not entirely clear we can route reply without complete OEM group.
    // TODO: consider adding a way to suppress malformed replies.
    if (*dataLen < groupMagicSize)
    {
        std::fprintf(stderr, "NetFn:[0x2E], OEM:[%zu bytes?], Cmd:[%#04X]\n",
                     *dataLen, cmd);
        (*dataLen) = 0;
        return IPMI_CC_REQ_DATA_LEN_INVALID;
    }

    // Find registered handler or reject request.
    auto number = toOemNumber(reqBuf);
    auto cmdKey = std::make_pair(number, cmd);

    auto iter = handlers.find(cmdKey);
    if (iter == handlers.end())
    {
        auto wildKey = std::make_pair(number, IPMI_CMD_WILDCARD);
        iter = handlers.find(wildKey);
        if (iter == handlers.end())
        {
            std::fprintf(stderr,
                         "No Registered handler for NetFn:[0x2E], "
                         "OEM:[%#08X], Cmd:[%#04X]\n",
                         number, cmd);
            *dataLen = groupMagicSize;
            return IPMI_CC_INVALID;
        }
#ifdef __IPMI_DEBUG__
        std::fprintf(stderr,
                     "Wildcard NetFn:[0x2E], OEM:[%#08X], Cmd:[%#04X]\n",
                     number, cmd);
#endif
    }
    else
    {
#ifdef __IPMI_DEBUG__
        std::fprintf(stderr, "Match NetFn:[0x2E], OEM:[%#08X], Cmd:[%#04X]\n",
                     number, cmd);
#endif
    }

    // Copy OEMGroup here, by analogy to IPMI CC code at netfn router;
    // OemHandler should deal only with optional following data bytes.
    std::memcpy(replyBuf, reqBuf, groupMagicSize);

    size_t oemDataLen = *dataLen - groupMagicSize;
    Handler& handler = iter->second;

    auto rc = handler(cmd, reqBuf + groupMagicSize, replyBuf + groupMagicSize,
                      &oemDataLen);

    // Add OEMGroup bytes to nominal reply.
    *dataLen = oemDataLen + groupMagicSize;
    return rc;
}

// Function suitable for use as ipmi_netfn_router() call-back.
// Translates call-back pointer args to more specific types.
ipmi_ret_t ipmi_oem_wildcard_handler(ipmi_netfn_t /* netfn */, ipmi_cmd_t cmd,
                                     ipmi_request_t request,
                                     ipmi_response_t response,
                                     ipmi_data_len_t dataLen,
                                     ipmi_context_t context)
{
    // View requests & responses as byte sequences.
    const uint8_t* reqBuf = static_cast<uint8_t*>(request);
    uint8_t* replyBuf = static_cast<uint8_t*>(response);

    // View context as router object, defaulting nullptr to global object.
    auto router = static_cast<RouterImpl*>(context ? context : mutableRouter());

    // Send message parameters to dispatcher.
    return router->routeMsg(cmd, reqBuf, replyBuf, dataLen);
}

// Enable message routing to begin.
void RouterImpl::activate()
{
    // Register netfn 0x2e OEM Group, any (wildcard) command.
    std::printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_OEM_GROUP,
                IPMI_CMD_WILDCARD);
    ipmi_register_callback(NETFUN_OEM_GROUP, IPMI_CMD_WILDCARD, this,
                           ipmi_oem_wildcard_handler, PRIVILEGE_OEM);
}

void RouterImpl::registerHandler(Number oen, ipmi_cmd_t cmd, Handler handler)
{
    auto cmdKey = std::make_pair(oen, cmd);
    auto iter = handlers.find(cmdKey);
    if (iter == handlers.end())
    {
        // Add handler if key not already taken.
        handlers.emplace(cmdKey, handler);
    }
    else
    {
        std::fprintf(stderr,
                     "ERROR : Duplicate registration for NetFn:[0x2E], "
                     "OEM:[%#08X], Cmd:[%#04X]\n",
                     oen, cmd);
    }
}

} // namespace oem
