/*
 * objclient.h
 *
 *  Created on: 3 Jun 2013
 *      Author: john
 */

#ifndef OBJCLIENT_H_
#define OBJCLIENT_H_

#include <objlistener.h>
#include <klog.h>
#include <stdint.h>
#include <objectlist.h>
#include <rsmdict.h>
#include <semaphore.h>
#include <queue>

class cObjectClient : cKlog
{
private:
   class cMsgReg :cKlog
   {
   public:
      enum eMsgStatus
      {
         MSG_OK,
         MSG_ERROR,
         MSG_WAITING,
         MSG_BUSY
      };

      cMsgReg(cObjectList *);
      ~cMsgReg();
      void incTx();
      eMsgStatus rxStatus();
      cObjectList * getRxMsg();
      void setRxMsg(cObjectList *);
      void setStatus(eMsgStatus );
      bool msgMatch(KMsg *);
      bool msgComplete();
   private:
      eMsgStatus mStatus;
      int mTxCounter;
      cObjectList * mTxMsg;
      cObjectList * mRxMsg;
      KMsg * mKMsg;
      bool mMsgComplete;
   };

   class cEventPump : cKlog
   {
   public:
      cEventPump();
      ~cEventPump();
      void addListener(cObjectListener *l);
      void removeListener(cObjectListener *l);
      void pumpEvent(KMsg *);
   private:
      queue<cObjectList *> mEventQ;
      sem_t mQSem;
      list<cObjectListener *> mListeners;
      pthread_mutex_t mListenerMutex;
      static void * event_pump_thread(void *);
      void pump_events();
   } mEventPump;

   int mSocket;
   uint8_t mRxBuffer[2048];
   uint8_t mTxBuffer[2048];
   cObjectList * mRxMsg;
   pthread_mutex_t mRxMutex;
   pthread_cond_t mRxCond;
   pthread_mutex_t mTxMutex;
   pthread_cond_t mTxCond;
   std::queue<KMsg *> mTxQueue;
   std::list<cMsgReg *> mMsgRegistry;
   uint8_t mCurrMsgSeq;



   void ping();
   void service_rx();
   void service_tx();
   static void * rx_thread_function(void *args);
   static void * tx_thread_function(void *args);
   void tx_msg(KMsg *);
   cObjectList * send_msg(cObjectList *,bool wait_reply = false);
   void queue_rx_msg(KMsg * msg);
   void queue_tx_msg(KMsg * msg);
   void register_tx_msg(cMsgReg *);
   void unregister_tx_msg(cMsgReg *);
   bool update_tx_registry(KMsg * rx_msg);
   cObjectList * wait_msg();

public:
	cObjectClient();
   bool start(const char * host,int port);
	void addListener(cObjectListener *l);
	cObjectList * getIndexes(cObject *obj);
	cObject * get(cObject *idx);
	cObjectList * get(cObjectList *tx);
	int set(cObject*obj);
	void send(cObjectList * tx);
};


#endif /* OBJCLIENT_H_ */
