#ifndef POLL_HPP_
#define POLL_HPP_
#include "common.hpp"
#include "tout.hpp"
#include "fdtable.hpp"
#include <sys/epoll.h>


#ifndef SOCK_TIMEOUT
#define SOCK_TIMEOUT 60 // irc ping and socket timeout
#endif

#define EVENT_NONE  0
#define EVENT_IN    EPOLLIN
#define EVENT_OUT   EPOLLOUT
#define EVENT_CLOSE (EPOLLRDHUP|EPOLLERR|EPOLLHUP)
#define EVENT_ALL   (EVENT_IN|EVENT_OUT|EVENT_CLOSE)
#define EVENT_TOUT  EPOLLWAKEUP // as we should not need this


typedef uint32_t event_t; ///< event bitmask
typedef void (*poll_handler_t)(int, event_t);


class Poll {
    private:
        Poll();
        bool ctl(int, int, event_t);

        static Poll* inst;

        int efd;
        FdTable<poll_handler_t> handlers;
        ToutQueue timeouts;

        size_t fds;
        time_t activity;

    public:
        static INLINE Poll* getInst() { return inst ?: (inst = new Poll()); }
        ~Poll();

        bool add(int, poll_handler_t, event_t);
        bool mod(int, poll_handler_t, event_t);
        bool del(int);

        bool wait(int tout_ms); ///< waits for and processes events

        INLINE size_t num_fds() const { return fds; }
        INLINE time_t last_event() const { return activity; }
};


#endif