///
/// \file    connect.h
/// \author  Jan Chrin, PSI
/// \date    Release February: 2015
/// \version CAFE 1.0.0
///

#ifndef CONNECT_H
#define CONNECT_H

// generated by autotools
#include <config.h>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

#include <climits>

#include <global.h>

#include <exceptionsHelper.h>
#include <handleHelper.h>
#include <policyHelper.h>
#include <hashConduitGroup.h>

#if HAVE_BOOST_THREAD
#include <boost/thread/thread_only.hpp>
#include <boost/chrono.hpp>
#endif




class Connect
{ 	  
  protected:
  int  status;
  CAFEStatus cafeStatus;
  CAFEStatusSeverity cafeStatusSeverity;
 
  cafeConduit_set::iterator itcs;
  cafeGroup_set::iterator itgs;

  CAFEDataTypeCode cafeDataTypeCode;

  ExceptionsHelper exceptionsHelper;

  ChannelCreatePolicy channelCreatePolicy;
	
  PolicyHelper policyHelper;
  HandleHelper handleHelper;
  Helper helper;

  std::string deviceAttributeDeliminator;

  bool pyCafeFlag;

  //connectCallbacks.cc
  static void callbackHandlerAccessRights(struct access_rights_handler_args args);

  static void callbackHandlerException   (struct exception_handler_args     args);

  //connect.cpp
  int  createChannel(unsigned int  handle, const char * pv, chid &pCh);
	int  createHandle(const char * pv, ca_client_context * ccc, unsigned int  &handle)
  //int  createHandle(const char * pv, ca_client_context * ccc, ChannelRequestPolicy channelRequestPolicyPut, unsigned int  &handle)
          throw (CAFEException_pv);

  int  contextDestroy();
  int  contextDestroy(ca_client_context * cctLocal);

  unsigned short epicsVersion(unsigned short & major, unsigned short & minor, unsigned short & patch);

  //group functions

  int  createChannelWithinGroup(unsigned int  handle, const char * pv, chid &pCh);
  int  createHandleWithinGroup(const char  * pv, ca_client_context * ccc, unsigned int  & _handle)
          throw (CAFEException_pv);

  public:
	
	
  Connect(){

    channelMonitorPolicy.setPolicy(
       (ChannelWhenToFlushSendBufferPolicyKind) CAFENUM::FLUSH_AFTER_EACH_CHANNEL_SUBSCRIPTION,
		CAFENUM::WITH_FLUSH_IO, DEFAULT_TIMEOUT_PEND_IO);

    channelOpenGroupPolicy.setPolicy(
                                     CAFENUM::FLUSH_AFTER_EACH_GROUP_CREATION,
                                     CAFENUM::WITH_PEND_EVENT, DEFAULT_TIMEOUT_SG_PEND_EVENT);

    channelOpenPolicy.setPolicy(
                                CAFENUM::FLUSH_AFTER_EACH_CHANNEL_CREATION,
                                CAFENUM::WITH_PEND_EVENT, DEFAULT_TIMEOUT_PEND_EVENT);

    deviceAttributeDeliminator=DEFAULT_DEVICE_ATTRIBUTE_DELIMINATOR;
		
#if HAVE_PYTHON_H
    pyCafeFlag=true;
#else
		pyCafeFlag=false;		
#endif	 
  };

  //these need to be public

  PrintErrorPolicy printErrorPolicy;

  ChannelOpenPolicy channelOpenPolicy;
  ChannelOpenPolicy channelClosePolicy; //can also use for close
  ChannelOpenPolicy channelMonitorPolicy;
  ChannelOpenPolicy channelOpenGroupPolicy;
	
	
  //28 May 2017
  ChannelRequestPolicy channelRequestPolicyMasterPut;
	ChannelRequestPolicy channelRequestPolicyMasterGet;
	ChannelRequestPolicy channelRequestPolicyMasterGetCtrl;
	ChannelGetActionWhenMonitorPolicy channelGetActionWhenMonitorPolicyMaster;

  //ChannelOpenPolicy getChannelOpenPolicy(){return channelOpenPolicy;}
  //ChannelOpenPolicy getChannelClosePolicy(){return channelClosePolicy;}
  //ChannelOpenPolicy getChannelMonitorPolicy(){return channelMonitorPolicy;}
  //ChannelOpenPolicy getChannelOpenGroupPolicy(){return channelOpenGroupPolicy;}

  HandleHelper getHandleHelper()    {return handleHelper;}
  HandleHelper getInfo()    {return handleHelper;}
  PolicyHelper getPolicyHelper()  {return policyHelper;}
  PolicyHelper getPolicy()  {return policyHelper;}

  unsigned int getNelemClient(unsigned int h){ return handleHelper.getNelemClient(h);}
  unsigned int getNelemNative(unsigned int h){ return handleHelper.getNelemNative(h);}
  unsigned int getNelemRequest(unsigned int h){ return handleHelper.getNelemRequest(h);}

  int  getStatus() {return status;}

  CAFEStatus          getCafeStatus() {return cafeStatus;}
	CAFEStatusSeverity  getCafeStatusSeverity() {return cafeStatusSeverity;}
	
	int flushNow() {return ca_flush_io();}
	
	int _ca_flush_io(){return ca_flush_io();}
	int _ca_poll(){return ca_poll();}
	int _ca_pend_io(double t){return ca_pend_io(t);}
	int _ca_pend_event(double t){return ca_pend_event(t);}
	
  //connect.cc
	bool setPyCafe(bool b){return pyCafeFlag=b;};
	bool getPyCafe(){return pyCafeFlag;} ;
  int  init() throw (CAFEException_init);
  int  init(ca_preemptive_callback_select select)  throw (CAFEException_init);

  //std::string
  int  open(const string pvS, unsigned int  &handle) throw (CAFEException_open){
      try { open (pvS.c_str(), handle);} catch(CAFEException_open &e) {throw e;};
  }
  int  open(const string pvS, const std::string pvAliasS, unsigned int  &handle)
          throw (CAFEException_open){
      try { open (pvS.c_str(), pvAliasS.c_str(), handle);} catch(CAFEException_open &e) {throw e;};
  }
  int  open(const string *pvArrayS, unsigned int *handleArray, const unsigned int nHandles)
          throw (CAFEException_open);

  //const char *pv
  int  open(const char *pv, unsigned int  &handle) throw (CAFEException_open);
  int  open(const char *pv, const char *pvAlias, unsigned int  &handle)
          throw (CAFEException_open);

  int  open(const char **pvArray, unsigned int *handleArray, const unsigned int nHandles)
          throw (CAFEException_open);
  int  open(vector<const char *>, vector<unsigned int> &) throw (CAFEException_open);
  int  open(vector<string>, vector<unsigned int> &) throw (CAFEException_open);

  int  openV(vector<string> s, vector<unsigned int> &i) throw (CAFEException_open)
  {return open(s,i); };

  
//################################################################################	

  	
	void openGroupPrepare(){
		channelOpenGroupPolicy.setFlushSendBufferKind(WITH_PEND_EVENT);
		channelOpenGroupPolicy.setWhenToFlushSendBuffer(FLUSH_DESIGNATED_TO_CLIENT);
		return;	
	}
		
	void openMonitorPrepare(){
	  channelMonitorPolicy.setFlushSendBufferKind(WITH_FLUSH_IO);
	  channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_DESIGNATED_TO_CLIENT);
		return;
	}	

	double setOpenDefaultPendTime(double _timeout){
		return channelOpenPolicy.setDefaultTimeout(_timeout);
	}
	
	double getOpenDefaultPendTime(){
		return channelOpenPolicy.getDefaultTimeout();
	}

				
	void openGroupNowAndWait(double _timeout){
		double dto = channelOpenGroupPolicy.getTimeout();
		channelOpenGroupPolicy.setTimeout(_timeout);
		channelOpenGroupPolicy.flushSendBufferNow();
		//	
		//reset
		channelOpenGroupPolicy.setWhenToFlushSendBuffer(FLUSH_NOW);
		channelOpenGroupPolicy.setFlushSendBufferKind(WITH_PEND_EVENT);	
		//channelOpenGroupPolicy.setTimeoutToDefault();
		channelOpenGroupPolicy.setTimeout(dto);
		return;
	}

	void openMonitorNow(){
		channelMonitorPolicy.flushSendBufferNow();
		//reset
		channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_NOW);
		channelMonitorPolicy.setFlushSendBufferKind(WITH_FLUSH_IO);	
		return;
	}
	
	void openMonitorNowAndWait(double _timeout){
		channelMonitorPolicy.setTimeout(_timeout);
		channelMonitorPolicy.flushSendBufferNow();		
		//reset
		channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_NOW);
		channelMonitorPolicy.setFlushSendBufferKind(WITH_FLUSH_IO);		
		return;
  }

  void openPrepare() {
     channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT);
		 channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_DESIGNATED_TO_CLIENT);
		 return;
	} 
	
  void openNowAndWait(double _timeout) {
	  double dto = channelOpenPolicy.getTimeout();
	  channelOpenPolicy.setTimeout(_timeout);
	  channelOpenPolicy.flushSendBufferNow();
		//reset 
		channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_NOW);
		channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT);
		//channelOpenPolicy.setTimeoutToDefault();
		channelOpenPolicy.setTimeout(dto);
		return;
	} 
	
  void openNow() {
	  channelOpenPolicy.flushSendBufferNow();
		channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_NOW);
		channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT);
		return;
	} 
	
	void openNoWait(){
		channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT);		
		channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_DESIGNATED_TO_CLIENT);
		return;
	}
	
	bool initCallbackComplete(vector<unsigned int> hV) {
		return initCallbackComplete(&hV[0], hV.size());
	}
	
	bool initCallbackComplete(unsigned int * hArray, unsigned int nelem);

	
	
	//#################################################################################			

  unsigned int  printHandle(unsigned int  h){return handleHelper.printHandle(h);};
  unsigned int  printHandles(void){return handleHelper.printHandles();};
  unsigned int  printDisconnectedHandles(void){return handleHelper.printDisconnectedHandles();};
  unsigned int  getDisconnectedHandles(vector<unsigned int> &dhV, vector<string> &pvV)
	{return handleHelper.getDisconnectedHandles(dhV, pvV);};


  void printCAFEException_pv(CAFEException_pv & e){exceptionsHelper.printCAFEException_pv(e);};
  
	
	
	
	
	
  //closeChannel(s) only close within a context
	int  closeChannels(unsigned int * handleArray, unsigned int nHandles);
	int  closeChannels(vector<unsigned int> v){
	
	  //unsigned int * handleArray = new unsigned int[v.size()];
		//int status= closeChannels(handleArray, v.size());
		//delete [] handleArray;
	  //return status;
		return closeChannels(&v[0], v.size());
	};
  int  closeChannelsV(vector<unsigned int> v){
	  //unsigned int * handleArray = new unsigned int[v.size()];
		//int status= closeChannels(handleArray, v.size());
		//delete [] handleArray;		
	  //return status;
		return closeChannels(&v[0], v.size());
	};
	
	
  int  close(unsigned int  handle);
  int  closeChannel(unsigned int  handle){return close(handle);};
  int  closeChannels();
  int  closeChannels(ca_client_context * cctLocal);
  int  close(){return closeChannels();};
  
  //closeHandle(s) close regardless of context
	int  closeHandlesV(vector<unsigned int> v){ return closeHandles(&v[0], v.size());}
	int  closeHandles (vector<unsigned int> v){ return closeHandles(&v[0], v.size());}
	
	
  int  closeHandles(unsigned int * handleArray, unsigned int nHandles);
  int  closeHandle(unsigned int  handle);
  int  closeHandles();
 
  // Monitors
  int  monitorStart(unsigned int  handle, MonitorPolicy &mp);
  int  monitorStart(unsigned int  handle, unsigned int  & monitorID);
  int  monitorStart(unsigned int  handle) {
      unsigned int monitorID; return monitorStart(handle, monitorID);
  }

  int  monitorStop (unsigned int  handle, MonitorPolicy mp);
  int  monitorStop (unsigned int  handle, unsigned int  monitorID);
  int  monitorStopWithID (unsigned int  handle, unsigned int  monitorID){
      return monitorStop(handle, monitorID);}
  int  monitorStop (unsigned int  handle); //stop all monitors for this handle
  int  monitorStop ();
  int  monitorStopAll (){return monitorStop();};
  int  monitorStop (ca_client_context * ccc);

  // Monitors for arrays and vectors
  int  monitorStart(unsigned int  * handleArray, unsigned int  nelem) {
      int * statusArray = new int[nelem];
      MonitorPolicy * mpV = new MonitorPolicy[nelem];
      status = monitorStart (handleArray, nelem, statusArray, mpV);
      delete [] statusArray; delete [] mpV;
      return status;
  }

  int  monitorStart(unsigned int  * handleArray, unsigned int  nelem, int  *statusArray,
                    MonitorPolicy * mpV);
  int  monitorStart(unsigned int  * handleArray, unsigned int  nelem, int  *statusArray,
                    unsigned int  * monitorIDArray);
  int  monitorStart(vector<unsigned int> handleV, vector<int> &statusV,
                    vector<MonitorPolicy> &mpV);
  int  monitorStart(vector<unsigned int> handleV, vector<int> &statusV,
                    vector<unsigned int> &monitorIDV);
  int  monitorStop (unsigned int  * handleArray, unsigned int  nelem, int  *statusArray);
  int  monitorStop (vector<unsigned int> handleV, vector<int> &statusV);

  int  monitorStop(unsigned int  * handleArray, unsigned int  nelem) {
      int * statusArray = new int[nelem];
      status = monitorStop (handleArray, nelem, statusArray);
      delete [] statusArray;
      return status;			
  }


  MonitorPolicy * createMonitorPolicyArray(const unsigned int nmp) {
		MonitorPolicy * mpArray = new MonitorPolicy[nmp];
		return mpArray;		
	}

  int  terminate();
  int  terminate(ca_client_context * cctLocal);
 
  unsigned int getHandleFromPV(const char * pv) {return handleHelper.getHandleFromPV(pv); }
  const char * getPVFromHandle(unsigned int handle){
      return handleHelper.getPVFromHandle(handle);
  }



  unsigned int getHandleFromPVWithinGroup(const char * pv, unsigned int grh) {
	  return handleHelper.getHandleFromPVWithinGroup(pv, grh); }


  bool isEnum(unsigned int handle) {return handleHelper.isEnum(handle);}

  bool isValid(unsigned int handle) { for (itcs = cs.begin(); itcs != cs.end(); ++itcs)
    {if ((*itcs).getHandle()==handle) {return true;}} return false;}

  bool allChannelsConnected() { for (itcs = cs.begin(); itcs != cs.end(); ++itcs)
      {if (!(*itcs).isConnected()) {return false;}} return true;}
			
  bool isConnected(unsigned int handle) {
      return isChannelConnected(handle);
  }
	
  bool isChannelConnected(unsigned int handle){cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
        cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
        if (it_handle != handle_index.end()) {return (*it_handle).isConnected();}
        else {std::cout<< "Input handle " << handle << " does not exists! " << std::endl; return false;}}
  int  getChannelInfo(unsigned int handle, ChannelRegalia & channelInfo){
      cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
      cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
      if (it_handle != handle_index.end()) {channelInfo=(*it_handle).getChannelRegalia(); return ICAFE_NORMAL;}
      else {return ECAFE_INVALID_HANDLE;}
  };	
  chid getChannelID(unsigned int handle){cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
      cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
      if (it_handle != handle_index.end()) {return (*it_handle).getChannelID();}
      else {std::cout<< "Input handle " << handle << " does not exists! " << std::endl; return NULL;}}


  ca_client_context * getClientContext(const char * pvname){
       return handleHelper.getContextFromPV(pvname);
  }

  ca_client_context * getClientContext(unsigned int handle){
       return handleHelper.getContextFromHandle(handle);
  }

  int attachContext(ca_client_context *ccc){
      if (ccc != NULL) {
        return ca_attach_context(ccc);
    } else { return ECAFE_NULLCONTEXT;}
  }

  int attachContextByPVName(const char * pvname){
      ca_client_context * ccc=getClientContext(pvname);
      if (ccc != NULL) {
        return ca_attach_context(ccc);
    } else { return ECAFE_NULLCONTEXT;}
  }

  int attachContextByHandle(unsigned int handle){
      ca_client_context * ccc=getClientContext(handle);
      if (ccc != NULL) {
        return ca_attach_context(ccc);
    } else { return ECAFE_NULLCONTEXT;}
  }

  //Add these methods for QCafe
  int updateAccessRead(unsigned int handle, int ar) {cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
      cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
      if (it_handle != handle_index.end()) {

          if ( (*it_handle).getAccessRead() != ar ) {
              if(MUTEX){cafeMutex.lock();}
              handle_index.modify(it_handle, change_accessRead(ar));
              if(MUTEX){cafeMutex.unlock();}
          }
          return ICAFE_NORMAL;}
      else {std::cout<< "Input handle " << handle << " does not exists! " << std::endl;
          return ECAFE_INVALID_HANDLE;}
  }

  int updateAccessWrite(unsigned int handle, int aw) {cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
      cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
      if (it_handle != handle_index.end()) {
          if ( (*it_handle).getAccessWrite() != aw ) {
              if(MUTEX){cafeMutex.lock();}
              handle_index.modify(it_handle, change_accessWrite(aw));
              if(MUTEX){cafeMutex.unlock();}
          }
          return ICAFE_NORMAL;}
      else {std::cout<< "Input handle " << handle << " does not exists! " << std::endl;
          return ECAFE_INVALID_HANDLE;}
  }

  bool getReadAccess(unsigned int handle){cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
      cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
      if (it_handle != handle_index.end()) {return (bool) (*it_handle).getAccessRead();}
      else {std::cout<< "Input handle " << handle << " does not exists! " << std::endl; return false;}}

  bool getWriteAccess(unsigned int handle){cafeConduit_set_by_handle & handle_index=cs.get<by_handle>();
      cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handle);
      if (it_handle != handle_index.end()) {return (bool) (*it_handle).getAccessWrite();}
      else {std::cout<< "Input handle " << handle << " does not exists! " << std::endl; return false;}}

  void printStatusMessage(int status) {
      string s =  getCafeStatus().csi.message(status);
      string c =  getCafeStatus().csc.message(status);
      printf("%s\n",c.c_str());
      printf("%s\n",s.c_str());
  }

  int  printStatus(unsigned int handle, int  status);
  int  printStatusIfError(unsigned int handle, int  status);
  int  printStatus(unsigned int * handleArray, unsigned int  nelem, int  * statusArray);
  int  printStatusIfError(unsigned int * handleArray, unsigned int  nelem, int  * statusArray);
  int  printStatus(vector<unsigned int> handleV, vector<int> statusV);
  int  printStatusIfError(vector<unsigned int> handleV, vector<int> statusV);


  int  setPVAlias(unsigned int handle, const char * pv) throw (CAFEException_open);

  // GROUP FUNCTIONS

  PVDataHolder * getPVData(vector <unsigned int> handleArray);

  int  collectionDefine(const char * collectionName, vector<string> deviceV);
  int  collectionDefine(const char * collectionName, vector<const char *> deviceV);
  int  collectionDefine(const char * collectionName, pv_string_t * deviceArray, unsigned int  deviceLength);
  int  collectionFetch(const char * collectionName, vector<string> &deviceListV);
  int  collectionFetch(const char * collectionName, vector<const char *> &deviceListV);
  int  collectionFetch(const char * collectionName,deviceCollection &dC);
  vector<deviceCollection> getCollections() const {return deviceCollectionV;};


  //To do: Add shared_ptr for this method to ensure memory release
  int  collectionMemberList(const char * collectionName, boost::shared_ptr<pv_string_t []> &list, unsigned int  &listLength);
  //int  collectionMemberList(const char * collectionName, dbr_string_t * &list, unsigned int  &listLength);

  //To do: Add shared_ptr for this method to ensure memory release
  int  collectionList      (boost::shared_ptr<pv_string_t []> &clist, unsigned int  &listLength);
  //int  collectionList      (dbr_string_t * &clist, unsigned int  &listLength);

  int  collectionMemberList(const char * collectionName, vector<string> &list);
  int  collectionList      (vector<string> &clist);

	int  devicePositionOrderedMultiMap(const char * collectionName, std::multimap<float, string> &posDev);
	int  devicePositionMap(const char * collectionName, std::map<float, string> &posDev);
  int  devicePositionV(const char * collectionName, std::vector<string> &dev, std::vector<float> &pos);


  int  fetchIndexOfCollectionMember(const char *collectionName, const char * deviceName);

  bool isGroup(const char *);
  bool isCollection(const char *);

  int  groupOpen(const char *pv,   unsigned int  &groupHandle) throw (CAFEException_groupOpen);
  int  groupOpen(PVGroup &pvgroup, unsigned int  &groupHandle) throw (CAFEException_groupOpen);


  int  groupClose(unsigned int  groupHandle);
	int  groupClose();
	int  groupCloseAll(){return groupClose(); };
  int  groupHandleErase();
  int  groupHandleErase(ca_client_context *ccc);

  int  groupCombine(const char * newGroupName, const char * groupName1,
                            const char * groupName2);  // PVGroup &pvGroup);
  int  groupCombine(const char * newGroupName, vector<char *> groupName);// PVGroup &pvGroup);


  vector<string> generateChannelList(vector<string> inputStringV) {
		return  getFromGlobalChannelList(inputStringV);
	}
 
  vector<string> getFromGlobalChannelList(vector<string>);


  int  groupDefine (const char * groupName, const char * collectionName, vector<string> attributeV);
  int  groupDefine (const char * groupName, const char * collectionName, vector<const char*> attributeV);
  int  groupDefine (const char * groupName, const char * collectionName,
                    pv_string_t * attributeArray, unsigned short attributeLength);
  int  groupDefine (const char * groupName, const char * collectionName, pv_string_t  attribute){
     pv_string_t aA[1]; strcpy(aA[0], attribute);
     return groupDefine(groupName, collectionName, aA, 1);
  }

  int  groupDefine (const char * groupName, vector<string> deviceV, vector<string> attributeV);// PVGroup &pvGroup);
  int  groupDefine (const char * groupName, vector<const char *> deviceV, vector<const char*> attributeV);
                    //PVGroup &pvGroup);
  int  groupDefine (const char * groupName, pv_string_t * deviceArray, unsigned int  deviceLength,
                    pv_string_t * attributeArray, unsigned short attributeLength); //

  int  groupDefine (const char * groupName, vector<string> pvArrayV); // PVGroup &pvGroup);
  int  groupDefine (const char * groupName, vector<const char *> pvArrayV); // PVGroup &pvGroup);
  int  groupDefine (const char * groupName, pv_string_t * pvArray, unsigned int  pvArrayLength);
                            //PVGroup &pvGroup);

  //To do: Add shared_ptr for this method to ensure memory release

  int  groupMemberList(const char * groupName, boost::shared_ptr<pv_string_t []> &list, unsigned int &listLength);
  //int  groupMemberList(const char * groupName, dbr_string_t * &list, unsigned int  &listLength);

  int  groupList      (boost::shared_ptr<pv_string_t []> &glist, unsigned int  &listLength);
  //int  groupList      (dbr_string_t * &glist, unsigned int  &listLength);

  int  groupMemberList(const char * groupName, vector<string> &list);

  int  groupList      (vector<string> &glist);

  int  fetchIndexOfGroupMember(const char *groupName, const char * pv);

  void setDeviceAttributeDeliminator(std::string d) {deviceAttributeDeliminator=d;};
  std::string getDeviceAttributeDeliminator() const {return deviceAttributeDeliminator;};
	

};

#endif // CONNECT_H
