/*
 * (c) 2005 Research Group Dr. Fuhrmann, University of Karlsruhe, Germany
 * All rights reserved.
 *
 * Author:
 *         Roman Krenicky
 *
 * $Id: epgigor_interface.h,v 1.14 2005/11/23 17:51:35 kutzner Exp $
 *
 */

/*
  epgigor_interface.h
  created: 1.12.2004
  last change: 24.7.2005
*/
/*! @file
    interface to the IGOR, adapted to the EPG part
*/

#ifndef _EPGIGOR_INTERFACE_H
#define _EPGIGOR_INTERFACE_H


#include "globalheader.h"

#include <string>
#include <thread.h>
#include <libigor.h>
#include "receiver.h"
#include "epgtypes.h"
extern "C"
{
  #include <time.h>
}


//! (sub-)types of IGOR VDR_EPG messages
enum epg_msgtype { epg_msgtype_none,  //!< no (known) VDR_EPG message at all
                   epg_msgtype_data,  //!< data message (VDR_EPG_DATA)
                   epg_msgtype_request,  //!< epg request (VDR_EPG_REQ)
                 };


/*! provides the plugin with the EPG specific IGOR interface

    on the one hand it provides methods for IGOR access, on the other hand it
    runs a separate thread, waiting for incoming messages
*/
class epgigor_interface : public cThread
{
  private:
   //! the @c receiver, incoming IGOR messages are passed to (via callback)
   receiver *listener; //!< @c ==NULL if none
   //! descriptor of the IGOR socket we're using, negative if no socket is in use
   int socket_descriptor;
   //! number of bytes received from the IGOR (resetable, may overflow)
   unsigned long in_bytes;
   //! mutex for @c in_bytes
   cMutex in_bytes_mutex;
   //! number of bytes transmitted to the IGOR (resetable, may overflow)
   unsigned long out_bytes;
   //! mutex for @c out_bytes
   cMutex out_bytes_mutex;
   //! size of the last message that can be sent on via @c igor_sendon() in bytes
   unsigned long last_sendon_candidate_size;


  private:
   epg_msgtype get_epg_msgtype (const char *msg, size_t len);
   time_t normalise_timeblock (time_t timeblock)
         {  return  timeblock - (timeblock % TIME_BLOCK_SIZE);  }
   bool extract_data_msg (const char *msg, size_t len, epgchannel *channel,
                          time_t *timeblock, bool *update, epgdata *data);
   bool extract_request_msg (const char *msg, size_t len,
                             epgchannel *channel, time_t *timeblock,
                             bool *update);
   bool create_data_msg (const epgchannel &channel, time_t timeblock,
                         bool update, const epgdata &data, string *msg);
   bool create_request_msg (const epgchannel &channel, time_t timeblock,
                            bool update, string *msg);
   string calculate_destination (const epgchannel &channel,
                                 time_t timeblock);
   bool pack_igor_address (const string &key, sa_igor *address);
   bool pack_igor_address (const char *key, sa_igor *address);

  protected:
   virtual void Action (void);

  public:
   epgigor_interface (void);
   virtual ~epgigor_interface (void);
   bool reconnect (void);
   bool initialised (void);
   bool connected (void);
   void Stop (void);
   void register_rcvr (receiver *listener);
   void deregister_rcvr (const receiver *listener);
   bool send_data (const epgchannel &channel, time_t timeblock,
                   const epgdata &data);
   bool send_resp (const epgchannel &channel, time_t timeblock, bool update,
                   const epgdata &data, const sa_igor &destination);
   bool send_req (const epgchannel &channel, time_t timeblock,
                  bool update = false);
   bool send_on_last_received_message (void);
   unsigned long get_bytes_received (void);
   unsigned long get_bytes_sent (void);
   unsigned long reset_bytes_received (void);
   unsigned long reset_bytes_sent (void);
}; // epgigor_interface


#endif // _EPGIGOR_INTERFACE_H
