#include "command_table.hpp"

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

#include <iomanip>
#include <main.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <user_channel/user_layer.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace phosphor::logging;

namespace ipmi
{
using Value = sdbusplus::message::variant<bool, uint8_t, int16_t, uint16_t,
                                          int32_t, uint32_t, int64_t, uint64_t,
                                          double, std::string>;

} // namespace ipmi

namespace command
{

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

    if (command)
    {
        log<level::DEBUG>(
            "Already Registered",
            phosphor::logging::entry("SKIPPED_ENTRY=0x%x", 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);

        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::shared_ptr<session::Session> session =
            std::get<session::Manager&>(singletonPool)
                .getSession(handler->sessionID);
        std::map<std::string, ipmi::Value> options = {
            {"userId", ipmi::Value(ipmi::ipmiUserGetUserId(session->userName))},
            {"privilege", ipmi::Value(static_cast<int>(session->curPrivLevel))},
        };
        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();

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

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

        auto 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)
        {
            log<level::ERR>("IPMI command timed out",
                            entry("DELAY=%d", 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::SESSION_ZERO))
    {
        errResponse.resize(1);
        errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
        log<level::INFO>("Table: Insufficient privilege for command",
                         entry("LUN=%x", command.lun()),
                         entry("NETFN=%x", command.netFn()),
                         entry("CMD=%x", command.cmd()));
        return errResponse;
    }

    return functor(commandData, *handler);
}

} // namespace command
