#include "message_handler.hpp"

#include "command_table.hpp"
#include "main.hpp"
#include "message.hpp"
#include "message_parsers.hpp"
#include "sessions_manager.hpp"

#include <sys/socket.h>

#include <memory>
#include <phosphor-logging/log.hpp>
#include <string>
#include <vector>

using namespace phosphor::logging;

namespace message
{

std::shared_ptr<Message> Handler::receive()
{
    std::vector<uint8_t> packet;
    auto readStatus = 0;

    // Read the packet
    std::tie(readStatus, packet) = channel->read();

    // Read of the packet failed
    if (readStatus < 0)
    {
        log<level::ERR>("Error in Read", entry("STATUS=%x", readStatus));
        return nullptr;
    }

    // Unflatten the packet
    std::shared_ptr<Message> message;
    std::tie(message, sessionHeader) = parser::unflatten(packet);

    auto session = std::get<session::Manager&>(singletonPool)
                       .getSession(message->bmcSessionID);

    sessionID = message->bmcSessionID;
    message->rcSessionID = session->getRCSessionID();
    session->updateLastTransactionTime();

    return message;
}

template <>
std::shared_ptr<Message> Handler::createResponse<PayloadType::IPMI>(
    std::vector<uint8_t>& output, std::shared_ptr<Message> inMessage)
{
    auto outMessage = std::make_shared<Message>();
    outMessage->payloadType = PayloadType::IPMI;

    outMessage->payload.resize(sizeof(LAN::header::Response) + output.size() +
                               sizeof(LAN::trailer::Response));

    auto reqHeader =
        reinterpret_cast<LAN::header::Request*>(inMessage->payload.data());
    auto respHeader =
        reinterpret_cast<LAN::header::Response*>(outMessage->payload.data());

    // Add IPMI LAN Message Response Header
    respHeader->rqaddr = reqHeader->rqaddr;
    respHeader->netfn = reqHeader->netfn | 0x04;
    respHeader->cs = crc8bit(&(respHeader->rqaddr), 2);
    respHeader->rsaddr = reqHeader->rsaddr;
    respHeader->rqseq = reqHeader->rqseq;
    respHeader->cmd = reqHeader->cmd;

    auto assembledSize = sizeof(LAN::header::Response);

    // Copy the output by the execution of the command
    std::copy(output.begin(), output.end(),
              outMessage->payload.begin() + assembledSize);
    assembledSize += output.size();

    // Add the IPMI LAN Message Trailer
    auto trailer = reinterpret_cast<LAN::trailer::Response*>(
        outMessage->payload.data() + assembledSize);
    trailer->checksum = crc8bit(&respHeader->rsaddr, assembledSize - 3);

    return outMessage;
}

std::shared_ptr<Message>
    Handler::executeCommand(std::shared_ptr<Message> inMessage)
{
    // Get the CommandID to map into the command table
    auto command = getCommand(inMessage);
    std::vector<uint8_t> output{};

    if (inMessage->payloadType == PayloadType::IPMI)
    {
        if (inMessage->payload.size() <
            (sizeof(LAN::header::Request) + sizeof(LAN::trailer::Request)))
        {
            return nullptr;
        }

        auto start = inMessage->payload.begin() + sizeof(LAN::header::Request);
        auto end = inMessage->payload.end() - sizeof(LAN::trailer::Request);
        std::vector<uint8_t> inPayload(start, end);

        output = std::get<command::Table&>(singletonPool)
                     .executeCommand(command, inPayload, *this);
    }
    else
    {
        output = std::get<command::Table&>(singletonPool)
                     .executeCommand(command, inMessage->payload, *this);
    }

    std::shared_ptr<Message> outMessage = nullptr;

    switch (inMessage->payloadType)
    {
        case PayloadType::IPMI:
            outMessage = createResponse<PayloadType::IPMI>(output, inMessage);
            break;
        case PayloadType::OPEN_SESSION_REQUEST:
            outMessage = createResponse<PayloadType::OPEN_SESSION_RESPONSE>(
                output, inMessage);
            break;
        case PayloadType::RAKP1:
            outMessage = createResponse<PayloadType::RAKP2>(output, inMessage);
            break;
        case PayloadType::RAKP3:
            outMessage = createResponse<PayloadType::RAKP4>(output, inMessage);
            break;
        case PayloadType::SOL:
            return outMessage;
            break;
        default:
            break;
    }

    outMessage->isPacketEncrypted = inMessage->isPacketEncrypted;
    outMessage->isPacketAuthenticated = inMessage->isPacketAuthenticated;
    outMessage->rcSessionID = inMessage->rcSessionID;
    outMessage->bmcSessionID = inMessage->bmcSessionID;

    return outMessage;
}

uint32_t Handler::getCommand(std::shared_ptr<Message> message)
{
    uint32_t command = 0;

    command |= (static_cast<uint8_t>(message->payloadType) << 16);
    if (message->payloadType == PayloadType::IPMI)
    {
        command |=
            ((reinterpret_cast<LAN::header::Request*>(message->payload.data()))
                 ->netfn)
            << 8;
        command |=
            (reinterpret_cast<LAN::header::Request*>(message->payload.data()))
                ->cmd;
    }

    return command;
}

void Handler::send(std::shared_ptr<Message> outMessage)
{
    auto session =
        std::get<session::Manager&>(singletonPool).getSession(sessionID);

    // Flatten the packet
    auto packet = parser::flatten(outMessage, sessionHeader, session);

    // Write the packet
    auto writeStatus = channel->write(packet);
    if (writeStatus < 0)
    {
        throw std::runtime_error("Error in writing to socket");
    }
}

void Handler::setChannelInSession() const
{
    auto session =
        std::get<session::Manager&>(singletonPool).getSession(sessionID);

    session->channelPtr = channel;
}

void Handler::sendSOLPayload(const std::vector<uint8_t>& input)
{
    auto session =
        std::get<session::Manager&>(singletonPool).getSession(sessionID);

    auto outMessage = std::make_shared<Message>();
    outMessage->payloadType = PayloadType::SOL;
    outMessage->payload = input;
    outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
    outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
    outMessage->rcSessionID = session->getRCSessionID();
    outMessage->bmcSessionID = sessionID;

    send(outMessage);
}

void Handler::sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd,
                                         const std::vector<uint8_t>& output)
{
    auto session =
        std::get<session::Manager&>(singletonPool).getSession(sessionID);

    auto outMessage = std::make_shared<Message>();
    outMessage->payloadType = PayloadType::IPMI;
    outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
    outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
    outMessage->rcSessionID = session->getRCSessionID();
    outMessage->bmcSessionID = sessionID;

    outMessage->payload.resize(sizeof(LAN::header::Request) + output.size() +
                               sizeof(LAN::trailer::Request));

    auto respHeader =
        reinterpret_cast<LAN::header::Request*>(outMessage->payload.data());

    // Add IPMI LAN Message Request Header
    respHeader->rsaddr = LAN::requesterBMCAddress;
    respHeader->netfn = (netfn << 0x02);
    respHeader->cs = crc8bit(&(respHeader->rsaddr), 2);
    respHeader->rqaddr = LAN::responderBMCAddress;
    respHeader->rqseq = 0;
    respHeader->cmd = cmd;

    auto assembledSize = sizeof(LAN::header::Request);

    // Copy the output by the execution of the command
    std::copy(output.begin(), output.end(),
              outMessage->payload.begin() + assembledSize);
    assembledSize += output.size();

    // Add the IPMI LAN Message Trailer
    auto trailer = reinterpret_cast<LAN::trailer::Request*>(
        outMessage->payload.data() + assembledSize);

    // Calculate the checksum for the field rqaddr in the header to the
    // command data, 3 corresponds to size of the fields before rqaddr( rsaddr,
    // netfn, cs).
    trailer->checksum = crc8bit(&respHeader->rqaddr, assembledSize - 3);

    send(outMessage);
}

} // namespace message
