// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/test/obs_ctrl/obsControlServer_mthread.cpp 432 2018-02-07 10:42:54Z depa $

// ICE
#include <Ice/Ice.h>
#include <IceUtil/Mutex.h>

//NICE
#include <Nice/Log.h>
// INDI
// #include <SystemSocket.hpp>
// #include <IndiXmlParser.hpp>
// #include <IndiProperty.hpp>
// #include <IndiMessage.hpp>

// BOOST
#include <boost/signals2/signal.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
// SHINS
#include "obsControl.h"
// #include "IndiClient.h"
// #include "listenerThread.h"
#include "os_sm.h"
#include "sequencerI.h"


// #include "shins_util.h"

//
// MAIN
//

// method to subscribe to onDataReceived signal
// compares the sent IndiProperty to set subsystem with the
// received one, in order to determine if command has been executed correctly.
// returns boolean accordingly
// Next step is to set state machine state
// void on_data_received(const pcf::IndiProperty& _sentProp,
//                       std::vector<pcf::IndiProperty>& _vecReceivedProp,
//                       bool& _isEqual)
// {
//   //
//   shins::itIndiProp_t it;
//   std::cout << "OS --->" << __FUNCTION__ << std::endl
//             << "OS ---> data received!" << std::endl;

//   std::cout << "OS ---> size for vec received = "
//             << _vecReceivedProp.size() << std::endl;
//   for (it = _vecReceivedProp.begin(); it < _vecReceivedProp.end(); ++it)
//     {
//       _isEqual = _sentProp.compareProperty(*it);
//       if (_isEqual)
//         {
//           std::cout << "OS ---> Command executed from subsystem";
//         }
//     }
// }


int main(int argc, char* argv[])
{
  int status = 0;
  std::string strAliasFileName = "/home/tan_unstable/SHARK-NIR/shins/branches/unstable/config/etc/alias.cfg";
  typedef IceUtil::Handle<SequencerI> SequencerIPtr;
  // Get the initialized property set.
  //
  Ice::PropertiesPtr props = Ice::createProperties(argc, argv);

  // Make sure that network and protocol tracing are off.
  //
  props->setProperty("Ice.LogFile", "/tmp/OS_Ice.log");
  LOG_FILE(::fopen("/tmp/wheelsCtrl_nice.log", "w+"));
  LOG_LEVEL(Nice::LDEBUG);
  I_LOG("===== OS START =====");
  // Initialize a communicator with these properties.
  //
  Ice::InitializationData id;
  id.properties = props;
  Ice::CommunicatorPtr ic = Ice::initialize(id);

  try {
    ic = Ice::initialize(argc, argv);

    osfsm::OSFsm m_stateMachine;
    boost::shared_ptr<osfsm::OSFsm> ptrStateMachine =
      boost::make_shared<osfsm::OSFsm>(m_stateMachine);

    IceUtil::Mutex m_mtxStateMachine;
    // boost::shared_ptr<IceUtil::Mutex> ptrMtxStateMachine =
    //   boost::make_shared<IceUtil::Mutex>(m_mtxStateMachine);

    // attaching to IIF ---------------------------------------
    // Ltcs::IifServiceWorkerInterfacePtr iif;
    // std::string endPointName = "CONNECT";
    // std::string serviceName = "IIF.SVC";// "Factory";
    // if(config()->getAtNode<Nice::Endpoint>(endPointName) != Nice::Endpoint())
    //   {
    //     // Nice::Endpoint p = config()->getAtNode<Nice::Endpoint>(endPointName);
    //     Nice::Endpoint ep = Nice::Endpoint::fromString("[NAME=ltcs.iif-svr,TCP=localhost:10000,TIMEOUT=10]");
    //     Nice::AppConfigClientPtr con = Nice::AppConfigClient::create(ep, config()->node("DATA"));
    //     iif = Ltcs::IifServiceWorkerInterface::create(config()->node("DATA."+serviceName));
    //   }
    // // --------------------------------------------------------

    Ice::ObjectAdapterPtr adapter =
      ic->createObjectAdapterWithEndpoints("SimpleObsControlAdapter", "default -p 10000");

    SequencerIPtr servant = new SequencerI(argc, argv, strAliasFileName,
                                           ptrStateMachine);//, m_mtxStateMachine);
    adapter->add(servant, ic->stringToIdentity("SimpleObsControlAdapter"));

    // variables used to initialize the listening thread 
    // std::vector<int> vecFd = servant->get_indiClient_fd();


    adapter->activate();

    ic->waitForShutdown();

    std::cout << " State Machine current state: " << m_stateMachine.current_state()[0]
              <<std::endl; 
  }catch (const Ice::Exception& e) {
    std::cerr << e << std::endl;
    status = 1;
  }catch (const char* msg) {
    std::cerr << msg << std::endl;
    status = 1;
  }
  if (ic) {
    try {
      ic->destroy();
    }catch (const Ice::Exception& e) {
      std::cerr << e << std::endl;
      status = 1;
    }
  }
  return status;
}
