#ifndef _LISTERNER_THREAD_
#define _LISTERNER_THREAD_

#include <fstream>
#include <queue>
#include <memory>
#include <stdexcept>
#include <sys/socket.h>
#include <sys/select.h>
#include <stdio.h>

#include <boost/signals2/signal.hpp>

#include <IceUtil/Thread.h>
#include <IceUtil/Mutex.h>

#include <Nice/Log.h>

#include <IndiMessage.hpp>
#include <IndiXmlParser.hpp>
#include <IndiProperty.hpp>

#include "os_sm.h"

// #include "shins_util.h"


class listenerThread : public IceUtil::Thread
{
public:
  typedef boost::signals2::signal<void (std::vector<pcf::IndiProperty>& )> signalReceivedData;
private:
  std::vector<int> m_vecSocketFd;
  int m_socketFd; //NOTE only m_vecSocketFd will remain
  // int* m_ptrMsgCounter;
  int m_msgCounter;
  IceUtil::Mutex* m_mtxCounter;
  IceUtil::Mutex m_mtxBuffer;
  std::vector<pcf::IndiProperty> m_vecRecvProperty;
  signalReceivedData m_sigPropertyReceived;
  // IceUtil::Mutex* m_mtxProp; // NOTE not sure if used... Not used yet

  // private methods
  std::string receive_data(const int &_socketFd);
  std::string remove_crnl(const std::string &_strIn);
  void decrease_counter();
  void increase_counter();
  std::string buffer_front(std::queue<std::string>& _buf);
  void buffer_pop(std::queue<std::string>& _buf);
  void buffer_push(std::queue<std::string>& _buf, std::string& _str);
  std::vector<pcf::IndiProperty> parse_data(const std::string &_str,
                                            std::queue<std::string>& _buf);
  void search_xml_block(const std::string &_strIn,
                        const std::string &_blockName,
                        std::vector<std::string::size_type> &_vecPosOpenOut,
                        std::vector<std::string::size_type> &_vecPosCloseOut);

public:
  listenerThread(IceUtil::Mutex &_mtxCounter,
                 int _msgCounter=0);

  listenerThread(const std::vector<int> &_vecSocketFd,
                 IceUtil::Mutex &_mtxCounter,
                 int _msgCounter=0);//,
                 // IceUtil::Mutex &_mtxProp);

  listenerThread(const int &_socketFd,
                 IceUtil::Mutex &_mtxCounter,
                 int _msgCounter=0);//,
                 // IceUtil::Mutex &_mtxProp);

  virtual ~listenerThread();
  virtual void run();
  void add_socket_fd(const int &_socketFd);
  int* get_ptr_counter();
  inline IceUtil::Mutex* get_ptr_mtx_counter(){return m_mtxCounter;}

  // NOTE Signal releted methods, sohuld build an interface
  boost::signals2::connection add_signal_onReceived(const signalReceivedData::slot_type& subscriber);
};

#endif // _LISTERNER_THREAD_
