/* Blinker
   Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org>
   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
   a blinkenarea.org project */

#ifndef BLINKER_CALLMGR_H
#define BLINKER_CALLMGR_H

#include <map>
#include <set>

#include "Io.h"
#include "IoCallee.h"
#include "Time.h"
#include "TimeCallee.h"

namespace Blinker {

/// callback manager, calls back at certain time or events
class CallMgr
{
protected:
  /// set of I/O callees to call for a certain I/O object
  typedef std::set<IoCallee *> IoCallees;
  /// what set of I/O callees to call for a certain I/O object
  typedef std::map<Io *, IoCallees> IoMap;

  /// set of time callees to call at a certain time
  typedef std::set<TimeCallee *> TimeCallees;
  /// what set of time callees to call at a certain time
  typedef std::map<Time, TimeCallees> TimeMap;
  /// when to call a time callee
  typedef std::map<TimeCallee *, Time> TimeCalleeMap;

public:
  /// constructor
  CallMgr();

  /// destructor
  ~CallMgr();

private:
  /// copy constructor disabled
  CallMgr(const CallMgr &that);

  /// assignment operator disabled
  const CallMgr & operator=(const CallMgr &that);

public:
  /**
   * @brief cancel callback at read I/O event
   * @param[in] callee whom not to call
   * @param[in] io I/O object not to monitor for readability any more
   */
  void cancelIoReadCall(IoCallee *callee, Io *io);

  /**
   * @brief request callback at read I/O event
   * @param[in] callee whom to call
   * @param[in] io I/O object to monitor for readability
   */
  void requestIoReadCall(IoCallee *callee, Io *io);

  /**
   * @brief cancel callback at write I/O event
   * @param[in] callee whom not to call
   * @param[in] io I/O object not to monitor for writability any more
   */
  void cancelIoWriteCall(IoCallee *callee, Io *io);

  /**
   * @brief request callback at write I/O event
   * @param[in] callee whom to call
   * @param[in] io I/O object to monitor for writability
   */
  void requestIoWriteCall(IoCallee *callee, Io *io);

  /**
   * @brief cancel callback at certain time
   * @param[in] callee whom not to call
   */
  void cancelTimeCall(TimeCallee *callee);

  /**
   * @brief request callback at certain time
   * @param[in] callee whom to call
   * @param[in] time when to call
   *
   * this cancels a previous time call request from callee
   */
  void requestTimeCall(TimeCallee *callee, const Time &time);

  /// run call manager
  void run();

protected:
  /// what I/O callees to call for readability on a certain I/O object
  IoMap m_iosRead;
  /// what I/O callees to call for writability on a certain I/O object
  IoMap m_iosWrite;

  /// what time callees to call at a certain time
  TimeMap m_times;
  /// when to call time callees
  TimeCalleeMap m_timeCallees;
}; // class CallMgr

} // namespace Blinker

#endif // #ifndef BLINKER_CALLMGR_H

