#pragma once

#include <cstddef>
#include <memory>
#include <numeric>
#include <vector>

namespace message
{

enum class PayloadType : uint8_t
{
    IPMI = 0x00,
    SOL = 0x01,
    OPEN_SESSION_REQUEST = 0x10,
    OPEN_SESSION_RESPONSE = 0x11,
    RAKP1 = 0x12,
    RAKP2 = 0x13,
    RAKP3 = 0x14,
    RAKP4 = 0x15,
    INVALID = 0xFF,
};

// RMCP Classes of Message as per section 13.1.3.
enum class ClassOfMsg : uint8_t
{
    RESERVED = 0x05,
    ASF = 0x06,
    IPMI = 0x07,
    OEM = 0x08,
};

#ifdef RMCP_PING
// RMCP Message Type as per section 13.1.3.
enum class RmcpMsgType : uint8_t
{
    PING = 0x80,
    PONG = 0x40,
};
#endif // RMCP_PING

namespace LAN
{

constexpr uint8_t requesterBMCAddress = 0x20;
constexpr uint8_t responderBMCAddress = 0x81;

namespace header
{

/**
 * @struct IPMI LAN Message Request Header
 */
struct Request
{
    uint8_t rsaddr;
    uint8_t netfn;
    uint8_t cs;
    uint8_t rqaddr;
    uint8_t rqseq;
    uint8_t cmd;
} __attribute__((packed));

/**
 * @struct IPMI LAN Message Response Header
 */
struct Response
{
    uint8_t rqaddr;
    uint8_t netfn;
    uint8_t cs;
    uint8_t rsaddr;
    uint8_t rqseq;
    uint8_t cmd;
} __attribute__((packed));

} // namespace header

namespace trailer
{

/**
 * @struct IPMI LAN Message Trailer
 */
struct Request
{
    uint8_t checksum;
} __attribute__((packed));

using Response = Request;

} // namespace trailer

} // namespace LAN

/**
 * @brief Calculate 8 bit 2's complement checksum
 *
 * Initialize checksum to 0. For each byte, checksum = (checksum + byte)
 * modulo 256. Then checksum = - checksum. When the checksum and the
 * bytes are added together, modulo 256, the result should be 0.
 */
static inline uint8_t crc8bit(const uint8_t* ptr, const size_t len)
{
    return (0x100 - std::accumulate(ptr, ptr + len, 0));
}

/**
 * @struct Message
 *
 * IPMI message is data encapsulated in an IPMI Session packet. The IPMI
 * Session packets are encapsulated in RMCP packets, which are encapsulated in
 * UDP datagrams. Refer Section 13.5 of IPMI specification(IPMI Messages
 * Encapsulation Under RMCP). IPMI payload is a special class of data
 * encapsulated in an IPMI session packet.
 */
struct Message
{
    static constexpr uint32_t MESSAGE_INVALID_SESSION_ID = 0xBADBADFF;

    Message() :
        payloadType(PayloadType::INVALID),
        rcSessionID(Message::MESSAGE_INVALID_SESSION_ID),
        bmcSessionID(Message::MESSAGE_INVALID_SESSION_ID),
        rmcpMsgClass(ClassOfMsg::RESERVED)
    {
    }

    /**
     * @brief Special behavior for copy constructor
     *
     * Based on incoming message state, the resulting message will have a
     * pre-baked state. This is used to simplify the flows for creating a
     * response message. For each pre-session state, the response message is
     * actually a different type of message. Once the session has been
     * established, the response type is the same as the request type.
     */
    Message(const Message& other) :
        isPacketEncrypted(other.isPacketEncrypted),
        isPacketAuthenticated(other.isPacketAuthenticated),
        payloadType(other.payloadType), rcSessionID(other.rcSessionID),
        bmcSessionID(other.bmcSessionID), rmcpMsgClass(other.rmcpMsgClass)
    {
        // special behavior for rmcp+ session creation
        if (PayloadType::OPEN_SESSION_REQUEST == other.payloadType)
        {
            payloadType = PayloadType::OPEN_SESSION_RESPONSE;
        }
        else if (PayloadType::RAKP1 == other.payloadType)
        {
            payloadType = PayloadType::RAKP2;
        }
        else if (PayloadType::RAKP3 == other.payloadType)
        {
            payloadType = PayloadType::RAKP4;
        }
    }
    Message& operator=(const Message&) = default;
    Message(Message&&) = default;
    Message& operator=(Message&&) = default;
    ~Message() = default;

    /**
     * @brief Extract the command from the IPMI payload
     *
     * @return Command ID in the incoming message
     */
    uint32_t getCommand()
    {
        uint32_t command = 0;

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

    /**
     * @brief Create the response IPMI message
     *
     * The IPMI outgoing message is constructed out of payload and the
     * corresponding fields are populated. For the payload type IPMI, the
     * LAN message header and trailer are added.
     *
     * @param[in] output - Payload for outgoing message
     *
     * @return Outgoing message on success and nullptr on failure
     */
    std::shared_ptr<Message> createResponse(std::vector<uint8_t>& output)
    {
        // SOL packets don't reply; return NULL
        if (payloadType == PayloadType::SOL)
        {
            return nullptr;
        }
        auto outMessage = std::make_shared<Message>(*this);

        if (payloadType == PayloadType::IPMI)
        {
            outMessage->payloadType = PayloadType::IPMI;

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

            auto reqHeader =
                reinterpret_cast<LAN::header::Request*>(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);
        }
        else
        {
            outMessage->payload = output;
        }
        return outMessage;
    }

    bool isPacketEncrypted;     // Message's Encryption Status
    bool isPacketAuthenticated; // Message's Authentication Status
    PayloadType payloadType;    // Type of message payload (IPMI,SOL ..etc)
    uint32_t rcSessionID;       // Remote Client's Session ID
    uint32_t bmcSessionID;      // BMC's session ID
    uint32_t sessionSeqNum;     // Session Sequence Number
    ClassOfMsg rmcpMsgClass;    // Class of Message
#ifdef RMCP_PING
    uint8_t asfMsgTag; // ASF Message Tag
#endif                 // RMCP_PING

    /** @brief Message payload
     *
     *  “Payloads” are a capability specified for RMCP+ that enable an IPMI
     *  session to carry types of traffic that are in addition to IPMI Messages.
     *  Payloads can be ‘standard’ or ‘OEM’.Standard payload types include IPMI
     *  Messages, messages for session setup under RMCP+, and the payload for
     *  the “Serial Over LAN” capability introduced in IPMI v2.0.
     */
    std::vector<uint8_t> payload;
};

} // namespace message
