#pragma once

#include <iostream>
#include <numeric>
#include "message.hpp"
#include "message_parsers.hpp"
#include "session.hpp"
#include "sol/console_buffer.hpp"

namespace message
{

class Handler
{
    public:
        explicit Handler(std::shared_ptr<udpsocket::Channel> channel,
                         uint32_t sessionID =
                             message::Message::MESSAGE_INVALID_SESSION_ID):
            sessionID(sessionID),
            channel(channel) {}

        Handler() = delete;
        ~Handler() = default;
        Handler(const Handler&) = default;
        Handler& operator=(const Handler&) = default;
        Handler(Handler&&) = default;
        Handler& operator=(Handler&&) = default;

        /**
         * @brief Receive the IPMI packet
         *
         * Read the data on the socket, get the parser based on the Session
         * header type and flatten the payload and generate the IPMI message
         *
         * @return IPMI Message on success and nullptr on failure
         *
         */
        std::unique_ptr<Message> receive();

        /**
         * @brief Process the incoming IPMI message
         *
         * The incoming message payload is handled and the command handler for
         * the Network function and Command is executed and the response message
         * is returned
         *
         * @param[in] inMessage - Incoming Message
         *
         * @return Outgoing message on success and nullptr on failure
         */
        std::unique_ptr<Message> executeCommand(Message& inMessage);

        /** @brief Send the outgoing message
         *
         *  The payload in the outgoing message is flattened and sent out on the
         *  socket
         *
         *  @param[in] outMessage - Outgoing Message
         */
        void send(Message& outMessage);

        /** @brief Set socket channel in session object */
        void setChannelInSession() const;

        /** @brief Send the SOL payload
         *
         *  The SOL payload is flattened and sent out on the socket
         *
         *  @param[in] input - SOL Payload
         */
        void sendSOLPayload(const sol::Buffer& input);

        /** @brief Send the unsolicited IPMI payload to the remote console.
         *
         *  This is used by commands like SOL activating, in which case the BMC
         *  has to notify the remote console that a SOL payload is activating
         *  on another channel.
         *
         *  @param[in] netfn - Net function.
         *  @param[in] cmd - Command.
         *  @param[in] input - Command request data.
         */
        void sendUnsolicitedIPMIPayload(uint8_t netfn,
                                        uint8_t cmd,
                                        const std::vector<uint8_t>& input);

        // BMC Session ID for the Channel
        session::SessionID sessionID;

    private:
        /** @brief Socket channel for communicating with the remote client.*/
        std::shared_ptr<udpsocket::Channel> channel;

        parser::SessionHeader sessionHeader  = parser::SessionHeader::IPMI20;

        /**
         * @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.
         *
         * @tparam[in] T - Outgoing message payload type
         * @param[in] output - Payload for outgoing message
         * @param[in] inMessage - Incoming IPMI message
         *
         * @return Outgoing message on success and nullptr on failure
         */
        template<PayloadType T>
        std::unique_ptr<Message> createResponse(std::vector<uint8_t>& output,
                                                Message& inMessage)
        {
            auto outMessage = std::make_unique<Message>();
            outMessage->payloadType = T;
            outMessage->payload = output;
            return outMessage;
        }

        /**
         * @brief Extract the command from the IPMI payload
         *
         * @param[in] message - Incoming message
         *
         * @return Command ID in the incoming message
         */
        uint32_t getCommand(Message& message);

        /**
         * @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.
         */
        uint8_t crc8bit(const uint8_t* ptr, const size_t len)
        {
            return (0x100 - std::accumulate(ptr,ptr+len,0));
        }

};

} //namespace message
