#ifndef BZOOK_CONTEXT_H
#define BZOOK_CONTEXT_H

#include <chrono>
#include <memory>
#include <set>
#include <functional>
#include <mutex>

namespace bzook
{

// Forward declarations.
class Socket;

class Context
{
public:
   friend class bzook::Socket;

   void forEachSocket(std::function<void(bzook::Socket&)> action);

   void shutdown(std::chrono::seconds socket_linger_timeout = std::chrono::seconds(1));

   static Context *get();
   static std::mutex &getLock();

   virtual ~Context();
private:
   Context();

   typedef void (*signal_handler)(int);

   void register_aggregate_handler(int signum, signal_handler handler, signal_handler *previous_handler);

   static void aggregate_interrupt_handler(int signum);
   static void aggregate_term_handler(int signum);

   static signal_handler previous_interrupt_handler;
   static signal_handler previous_term_handler;

   static std::unique_ptr<Context> _global_context;
   static std::mutex _global_mutex;

   void *_context_handle;
   std::set<bzook::Socket*> _registered_sockets;

   void register_socket(bzook::Socket *socket);
   void deregister_socket(bzook::Socket *socket);
};

}


#endif // BZOOK_CONTEXT_H
