//$Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/motion_ctrl/multiDevice.hpp 3765 2021-11-11 10:47:14Z depa $

#pragma once

#include <Nice/Util/Completion.h>
#include <Basda/ServiceStateMachine.h>
#include <Ice/Ice.h>
//#include <Nice/Log.h>

#include "common_sharknir.h"
#include "niceCallback.h"
#include "util/logger.h"
#include "data_mgr/fitsFileI.hpp"

class multiDevice
{
protected:
    int m_counter;
    std::string m_service;
    std::string m_objname;

    // number of devices
    std::size_t m_nDevices;
    std::vector<std::string> m_vecAliasName;
    // callback related objects
    boost::shared_ptr<niceCallback> m_ptrCallbackObj;
    boost::shared_ptr<niceCallback> m_ptrCallbackObjState;
    boost::function<void(const Nice::Completion&)> m_callbackFn;
    boost::function<void(const Nice::Completion&)> m_callbackFnCount;
    std::map<std::string, boost::function<void(const Nice::Completion&)> > m_mapCallbackFnReState;
    std::string m_strCallbackName;
    std::string m_strCallbackNameState;
    std::string m_strCallbackNameCount;
    std::string m_strCallbackNameHome;

    // state machine
    boost::function<void(const Basda::ServiceStateMachine&)> m_callbackFnState;
    const std::string __OBJ_NAME__;
    multiDevice(const std::vector<std::string>& _vecAliasName,
                // const Ice::LoggerPtr _ptrIceLogger,
                const std::string& objName) : __OBJ_NAME__(objName)
    {
        m_objname = objName;
        m_counter = 0;
        m_vecAliasName = _vecAliasName;
        m_nDevices = _vecAliasName.size();
        // m_ptrIceLogger = _ptrIceLogger;
        m_ptrCallbackObj = boost::make_shared<niceCallback>();
    }
public:
    multiDevice() {}

    virtual ~multiDevice() {}

    virtual void moveToReference() = 0;
    virtual void moveToReferenceStart() = 0;
    virtual void moveToReferenceWait(const Nice::Time& _time = Nice::Time()) = 0;

    virtual void moveDeviceToReference(const std::vector<std::string>& _vecDevAlias) = 0;
    virtual void moveDeviceToReferenceStart(const std::vector<std::string>& _vecDevAlias) = 0;
    virtual void moveDeviceToReferenceWait(const std::vector<std::string>& _vecDevAlias, const Nice::Time& _time = Nice::Time()) = 0;

    virtual void moveToNamedPosition(const std::map<std::string, int>& _mapPos) = 0;
    virtual void moveToNamedPositionStart(const std::map<std::string, int>& _mapPos) = 0;
    virtual void moveToNamedPositionWait(const std::map<std::string, int>& _mapPos, const Nice::Time& _time = Nice::Time()) = 0;

    virtual void moveToAbsolutePosition(const std::map<std::string, double>& _mapPos,      const std::map<std::string, std::string>& _mapUnit=std::map<std::string, std::string>()) = 0;
    virtual void moveToAbsolutePositionStart(const std::map<std::string, double>& _mapPos, const std::map<std::string, std::string>& _mapUnit=std::map<std::string, std::string>()) = 0;
    virtual void moveToAbsolutePositionWait(const std::map<std::string, double>& _mapPos,  const Nice::Time& _time = Nice::Time()) = 0;

    virtual void moveToRelativePosition(const std::map<std::string, double>& _mapPos,      const std::map<std::string, std::string>& _mapUnit=std::map<std::string, std::string>()) = 0;
    virtual void moveToRelativePositionStart(const std::map<std::string, double>& _mapPos, const std::map<std::string, std::string>& _mapUnit=std::map<std::string, std::string>()) = 0;
    virtual void moveToRelativePositionWait(const std::map<std::string, double>& _mapPos,  const Nice::Time& _time = Nice::Time()) = 0;

    virtual bool isDevice(const std::string& _strDevAlias) = 0;
    virtual std::size_t getNdevices() = 0;
    virtual std::vector<std::string> getNamedPosition(const std::vector<std::string>& _vecAlias) = 0;
    virtual std::vector<std::string> getNamedPosition(const std::size_t _deviceIdx) = 0;
    virtual Ice::Int getPosition(std::map<std::string, Ice::Double>& _mapPosition, const std::string& _unit="STEPS") = 0;
    virtual void set_callback_fn(boost::function<void(const Nice::Completion&)> & , const std::string &) = 0;
    virtual void emergencyAbort() = 0;
    virtual int stopAll() = 0;
    virtual int stop(const std::vector<std::string>& _vecDevAlias) = 0;
    virtual int abort(const std::vector<std::string>& _vecDevAlias) = 0;

};

