#ifndef IRC_MSG_HPP_
#define IRC_MSG_HPP_
#include "pool.hpp"
#include "common.hpp"
#include <queue>


#define IRC_MAX_MSG_LEN 512 // messages shall not exceed 512 characters in length, counting all characters including the trailing CR-LF

typedef char msg_t[IRC_MAX_MSG_LEN+1];
extern TPool<msg_t> messages; ///< global irc string pool


class MessageStreamIn {
    private:
        msg_t* buf;
        unsigned len;
        const int fd;

    public:
        MessageStreamIn(int);
        ~MessageStreamIn();

        ssize_t io(); ///< read()s from fd into internal buffer (error/eof/len). so should only read upon actual event.
        ssize_t pop(msg_t**); ///< returns parsed message, if any is ready (error/noop/len)
};


class MessageStreamOut {
    private:
        typedef struct {
            msg_t* buf;
            size_t len;
            size_t written;
        } reply_t;
        std::queue<reply_t> replies;

        bool cached_err; ///< there was an error that might be undetected so far - so return it from now on upon io() or send() to prevent inconsistent states.
        const int fd;

    public:
        MessageStreamOut(int);
        ~MessageStreamOut();

        bool io(); ///< write()s queued messages. false upon real error.
        bool send(msg_t*, size_t); ///< might enqueue operation, free's buf afterwards. NULL indicates a preliminary (formatting) error that is remembered.
        bool empty() const { return !cached_err && replies.empty(); } ///< pretend there is data when there actually only is an error to be detected
};


#endif