#include <mesytec-mnode/mnode_cpp_types.h>
#include <mesytec-mnode/mnode_nng.h>
#include <mesytec-mnode/mnode_nng_proto.h>

namespace mesytec::mnode::nng
{

size_t serialize_proto_to_nng(const google::protobuf::MessageLite &message, nng_msg *msg)
{
    auto messageSize = message.ByteSizeLong();

    if (nng_msg_realloc(msg, nng_msg_len(msg) + sizeof(u32) + messageSize))
        return 0;

    *reinterpret_cast<u32 *>(nng_msg_body(msg)) = messageSize;

    if (!message.SerializeToArray(reinterpret_cast<u8 *>(nng_msg_body(msg)) + sizeof(u32),
                                  messageSize))
    {
        return 0;
    }
    return sizeof(u32) + messageSize;
}

size_t deserialize_proto_from_nng(google::protobuf::MessageLite &message, nng_msg *msg)
{
    if (nng_msg_len(msg) < sizeof(u32))
        return 0;

    auto messageSize = *reinterpret_cast<u32 *>(nng_msg_body(msg));

    if (messageSize == 0)
        return 0;

    if (nng_msg_len(msg) < sizeof(u32) + messageSize)
        return 0;

    if (!message.ParseFromArray(reinterpret_cast<u8 *>(nng_msg_body(msg)) + sizeof(u32),
                                messageSize))
    {
        return 0;
    }

    return sizeof(u32) + messageSize;
}

size_t deserialize_proto_from_nng_trim(google::protobuf::MessageLite &message, nng_msg *msg)
{
    if (auto result = deserialize_proto_from_nng(message, msg))
    {
        nng_msg_trim(msg, result);
        return result;
    }

    return 0;
}

} // namespace mesytec::mnode::nng
