#include "command_table.hpp"

#include "main.hpp"
#include "message_handler.hpp"
#include "message_parsers.hpp"
#include "sessions_manager.hpp"

#include <ipmid/types.hpp>
#include <main.hpp>
#include <phosphor-logging/lg2.hpp>
#include <user_channel/user_layer.hpp>

#include <iomanip>

namespace command
{

void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
{
    auto& command = commandTable[inCommand.command];

    if (command)
    {
        lg2::debug("Already Registered: {COMMAND}", "COMMAND",
                   inCommand.command);
        return;
    }

    command = std::move(entry);
}

void Table::executeCommand(uint32_t inCommand,
                           std::vector<uint8_t>& commandData,
                           std::shared_ptr<message::Handler> handler)
{
    using namespace std::chrono_literals;

    auto iterator = commandTable.find(inCommand);

    if (iterator == commandTable.end())
    {
        CommandID command(inCommand);

        // Do not forward any session zero commands to ipmid
        if (handler->sessionID == session::sessionZero)
        {
            lg2::info(
                "Table: refuse to forward session-zero command: lun: {LUN}, netFn: {NETFN}, command: {COMMAND}",
                "LUN", command.lun(), "NETFN", command.netFn(), "COMMAND",
                command.cmd());
            return;
        }
        std::shared_ptr<session::Session> session =
            session::Manager::get().getSession(handler->sessionID);

        // Ignore messages that are not part of an active session
        auto state = static_cast<session::State>(session->state());
        if (state != session::State::active)
        {
            return;
        }

        auto bus = getSdBus();
        // forward the request onto the main ipmi queue
        using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
                                           std::vector<uint8_t>>;
        uint8_t lun = command.lun();
        uint8_t netFn = command.netFn();
        uint8_t cmd = command.cmd();

        std::map<std::string, ipmi::Value> options = {
            {"userId", ipmi::Value(static_cast<int>(
                           ipmi::ipmiUserGetUserId(session->userName)))},
            {"privilege",
             ipmi::Value(static_cast<int>(session->currentPrivilege()))},
            {"currentSessionId",
             ipmi::Value(static_cast<uint32_t>(session->getBMCSessionID()))},
        };
        bus->async_method_call(
            [handler, this](const boost::system::error_code& ec,
                            const IpmiDbusRspType& response) {
            if (!ec)
            {
                const uint8_t& cc = std::get<3>(response);
                const std::vector<uint8_t>& responseData =
                    std::get<4>(response);
                std::vector<uint8_t> payload;
                payload.reserve(1 + responseData.size());
                payload.push_back(cc);
                payload.insert(payload.end(), responseData.begin(),
                               responseData.end());
                handler->outPayload = std::move(payload);
            }
            else
            {
                std::vector<uint8_t> payload;
                payload.push_back(IPMI_CC_UNSPECIFIED_ERROR);
                handler->outPayload = std::move(payload);
            }
        },
            "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
            "xyz.openbmc_project.Ipmi.Server", "execute", netFn, lun, cmd,
            commandData, options);
    }
    else
    {
        auto start = std::chrono::steady_clock::now();

        // Ignore messages that are not part of an active/pre-active session
        if (handler->sessionID != session::sessionZero)
        {
            std::shared_ptr<session::Session> session =
                session::Manager::get().getSession(handler->sessionID);
            auto state = static_cast<session::State>(session->state());
            if ((state != session::State::setupInProgress) &&
                (state != session::State::active))
            {
                return;
            }
        }

        handler->outPayload = iterator->second->executeCommand(commandData,
                                                               handler);

        auto end = std::chrono::steady_clock::now();

        std::chrono::duration<size_t> elapsedSeconds =
            std::chrono::duration_cast<std::chrono::seconds>(end - start);

        // If command time execution time exceeds 2 seconds, log a time
        // exceeded message
        if (elapsedSeconds > 2s)
        {
            lg2::error("IPMI command timed out: {DELAY}", "DELAY",
                       elapsedSeconds.count());
        }
    }
}

std::vector<uint8_t>
    NetIpmidEntry::executeCommand(std::vector<uint8_t>& commandData,
                                  std::shared_ptr<message::Handler> handler)
{
    std::vector<uint8_t> errResponse;

    // Check if the command qualifies to be run prior to establishing a session
    if (!sessionless && (handler->sessionID == session::sessionZero))
    {
        errResponse.resize(1);
        errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
        lg2::info(
            "Table: Insufficient privilege for command: lun: {LUN}, netFn: {NETFN}, command: {COMMAND}",
            "LUN", command.lun(), "NETFN", command.netFn(), "COMMAND",
            command.cmd());
        return errResponse;
    }

    return functor(commandData, handler);
}

} // namespace command
