#include <cstdio>
#include <cstring>
#include <map>
#include <utility>

#include "host-ipmid/oemrouter.hpp"

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)
    {
        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())
        {
            fprintf(stderr, "No Registered handler for NetFn:[0x2E], "
                    "OEM:[%#08X], Cmd:[%#04X]\n", number, cmd);
            *dataLen = groupMagicSize;
            return IPMI_CC_INVALID;
        }
#ifdef __IPMI_DEBUG__
        fprintf(stderr, "Wildcard NetFn:[0x2E], OEM:[%#08X], Cmd:[%#04X]\n",
                number, cmd);
#endif
    }
    else
    {
#ifdef __IPMI_DEBUG__
        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.
    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
    {
        fprintf(stderr, "ERROR : Duplicate registration for NetFn:[0x2E], "
                "OEM:[%#08X], Cmd:[%#04X]\n", oen, cmd);
    }
}

}  // namespace oem
