#ifndef TILE_RPC_PROTOCOL_MESSAGE_H
#define TILE_RPC_PROTOCOL_MESSAGE_H

#pragma once

#include "tile/base/casting.h"
#include "tile/base/enum.h"

namespace tile {
class Message : public ExactMatchCastable {
public:
    virtual ~Message() = default;

    enum class Type : std::uint64_t {
        Single,
        Stream,// with both `StartOfStream` and `EndOfStream`
        StartOfStream = 1ULL << 62,
        EndOfStream   = 1ULL << 63
    };

    static constexpr std::uint64_t kNonmultiplexableCorrelationId = 1;
    virtual std::uint64_t GetCorrelationId() const noexcept       = 0;
    virtual Type GetType() const noexcept                         = 0;
};

class MessageFactory {
public:
    virtual ~MessageFactory() = default;

    enum class Type {
        Overloaded,   // Server side
        CircuitBroken,// Client side
    };

    virtual std::unique_ptr<Message> Create(Type type, std::uint64_t correlation_id, bool stream) const = 0;
    static const MessageFactory *null_factory;
};

TILE_DEFINE_ENUM_BITMASK_OPS(Message::Type);

}// namespace tile

#endif// TILE_RPC_PROTOCOL_MESSAGE_H
