// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/sasha_ctrl/scicamCtrlIndiDriver.h 1615 2019-03-20 14:09:29Z depa $

#pragma once

#include <string>
#include <ctime>
#include <stdexcept>
#include <vector>
#include <sstream>

#include <boost/typeof/typeof.hpp> // BOOST_AUTO
#include <boost/thread.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <Config.hpp>
#include <IndiDriver.hpp>
#include <IndiElement.hpp>
#include <IndiProperty.hpp>
#include <SystemSocket.hpp>

#include <Ice/Ice.h>

#include "util/shins_util.h"

class scicamCtrlIndiDriver : public pcf::IndiDriver
{
 private:
  std::string m_imageFileName;
  pcf::IndiProperty m_indiImageFileName;
  pcf::IndiProperty m_indiCommand;
  pcf::IndiProperty m_indiExposure;

  boost::thread_group thrdExposure;

  template <typename T> pcf::IndiProperty createIndiProperty(const std::string& _devName,
                                                             const std::string& _propName,
                                                             const pcf::IndiProperty::Type& _type,
                                                             const pcf::IndiProperty::PropertyPermType& _permType,
                                                             const pcf::IndiProperty::PropertyStateType & _stateType,
                                                             const std::map<std::string, T>& _mapElemNameVal);
                                                             // const std::vector<std::string>& _vecElemName,
                                                             // const std::vector<T>& _vecElemVal);

 public:
  scicamCtrlIndiDriver(const std::string& _szName,
                       const std::string& _szDriverVersion,
                       const std::string& _szProtocolVersion,
                       const std::string& _imageFileName);
  virtual ~scicamCtrlIndiDriver();
  virtual void handleGetProperties(const pcf::IndiProperty& _ipRecv);
  virtual void handleNewProperty(const pcf::IndiProperty& _ipRecv);
  virtual void execute();
};

template <typename T>
pcf::IndiProperty scicamCtrlIndiDriver::createIndiProperty(const std::string& _devName,
                                                           const std::string& _propName,
                                                           const pcf::IndiProperty::Type& _type,
                                                           const pcf::IndiProperty::PropertyPermType& _permType,
                                                           const pcf::IndiProperty::PropertyStateType & _stateType,
                                                           const std::map<std::string, T>& _mapElemNameVal)
                                                           // const std::vector<std::string>& _vecElemName,
                                                           // const std::vector<T>& _vecElemVal)
{
  pcf::IndiProperty retProperty = pcf::IndiProperty(_type);
  try{
    retProperty.setDevice(_devName);
    retProperty.setName(_propName);
    retProperty.setPerm(_permType);
    retProperty.setState(_stateType);

    for (BOOST_AUTO(it, _mapElemNameVal.begin()); it != _mapElemNameVal.end(); ++it)
      {
        retProperty.add(pcf::IndiElement(it->first));
        retProperty[it->first] = it->second;
      }
  }catch (std::exception err)
    {
      throw (err);
    }
  return retProperty;
}
