#ifndef LowerTestAdapter_h
#define LowerTestAdapter_h

#include <boost/algorithm/string.hpp>
#include <boost/shared_ptr.hpp>

#include "Helper/Singleton.h"
#include "Helper/Socket.h"
#include "Helper/GeneralConfigurationParams.h"
#include "Helper/Exceptions.h"
#include "Ports/AdapterConfigPort.h"
#include "Ports/DataPort.h"
#include "Messages/TrafficCaptureMessage.h"
#include "Dispatcher/Filter.h"

using namespace t3devlib;

class LowerTestAdapter : public Singleton<LowerTestAdapter>
{
 private:
  //! Singleton pattern implementation.
  friend class Singleton<LowerTestAdapter>;
  
  //! LowerTestAdapter.
  /*! Default ctor. Shall be declared in private part due to Singleton pattern implementation.
   */
  LowerTestAdapter();
  void SendMessage(TrafficCaptureMessage * pMsg);

 public:
  ~LowerTestAdapter();
  /** Register Data port to Lower Test Adapter
   * @param pPort: Pointer to Monitor port
   */
  void RegisterDataPort(DataPort *pPort);

  /** Register AdapterConfigPort port to Lower Test Adapter
   * @param pPort: Pointer to Adapter port
   */
  void RegisterAdapterConfigPort(AdapterConfigPort *pPort);

  /** Register a filter for a component
   * @param pComponent: Pointer to a ComponentId for which the filter is defined
   * @param filter: Filter details
   */
  void RegisterFilter(const ComponentId *pComponent, const FilterSet & filter);

  //! ConnectToCaptureServer
  /*! Configure and connect to the TrafficCapture process
   * @param sServerAddress: IP address to the TrafficCapture process (it acts as a sever)
   * @param iServerPort: Port number
   * @param filter: Global traffic capture filtering
   * @param ifaces: Netwotrk interfaces to monitor
   * @param mode: Traffic capture mode: on-line / off-line
   * @param record: Indicate if the TrafficCapture process should record the traffic
   * @param fileToPlay: In offline mode, this is the Pcap file name to play. It should be set to an empty string in real-line mode.
   */
  void ConnectToCaptureServer(boost::shared_ptr<GeneralConfigurationParams> configParams) throw (LowerTestAdapterException);
  //void ConnectToCaptureServer(const string& sServerAddress, const int iServerPort, const string& filter, const string& ifaces, unsigned char mode, unsigned char record, const string fileToPlay);

  //! ! StartCapture
  /*! Start the traffic capture
    */
  void StartCapture();

  //! StopCapture
  /*! Stop the traffic capture
    */
  void StopCapture();
  
  //! EnqueueMessage
  /*! Enqueues captured data to the component data port
   * @param pComp: pointer to the target component
   * @param pData: pointer to a buffer containing captured data
   * @param nDataLen: length of captured data (in bytes)
   */
  void EnqueueMessage(const ComponentId * pComp, const unsigned char * pData, int nDataLen);

 private:
  //! ! ProcessResponse
  /*! Process the TrafficCapture response message result to send it to TTCN-3 script.
   * @param result: result code
   */
  void ProcessResponse(const std::string& message, bool result);
  /* Main function for thread in charge of communication with 
   * TrafficCapture
   */
  static void Run();

  //! InitializeCapture
  /*! Configure and connect to the TrafficCapture process
   * @param filter: Global traffic capture filtering
   * @param ifaces: Netwotrk interfaces to monitor
   * @param mode: Traffic capture mode: on-line / off-line
   * @param record: Indicate if the TrafficCapture process should record the traffic
   * @param fileToPlay: In offline mode, this is the Pcap file name to play. It should be set to an empty string in real-line mode.
   */
  void InitializeCapture(boost::shared_ptr<GeneralConfigurationParams> configParams) throw (LowerTestAdapterException);
  //void InitializeCapture(const string& filter, const string& ifaces, unsigned char mode, unsigned char record, const string fileToPlay);

  /** This method is called whenever a captured packet is received 
   * from TrafficCapture. It dispatches the packet to Monitor port 
   * if associated filter matches.
   * @param pCapturedData: Pointer to a buffer containing captured data
   * @param nDataLen: Number of bytes in the buffer containing captured data
   */
  void ProcessCapturedData(const unsigned char * pCaptureData, unsigned int nDataLen);

  Socket * m_captureSocket;
  boost::thread * m_captureThread;
  DataPort * m_dataPort; // created and deleted by t3dk
  AdapterConfigPort * m_adapterConfigPort; // created and deleted by t3dk
  ComponentFilter m_filter;
};


#endif
