// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/tcs_iif/iifApp.cpp 3896 2022-04-13 13:24:17Z depa $

#include "iifApp.h"

int
iifApp::usage ( int _ret )
{
  std::cerr << "Usage: " << appName() << " --CONNECT:Endpoint=[..]\n";
  std::cerr << "Options:\n"
    "-h, --help                                       Show this message.\n"
    "-v, --version                                    Display version.\n"
    "\n"
    "\n"
    "--CONNECT:Endpoint=[NAME=NODENAME,...]          NAME=NODENAME  - name of the service\n"
    "                                                PORT=intval    - tcp port of the service\n"
    "                                                HOST=string    - tcp host address of the service\n"
    "                                                MULTICAST=true - resolve service by multicast\n"
    "\n"
    "Examples:\n"
    "\n";
  std::cerr  << appName() << " --CONNECT:Endpoint=[NAME=svc,HOST=host,PORT=4711]\n";
  std::cerr  << appName() << " --CONNECT:Endpoint=[NAME=svc,PORT=4711]\n";
  std::cerr  << appName() << " --CONNECT:Endpoint=[NAME=svc,MULTICAST=1]\n"
    "\n"
    "Hints:\n"
    " Don't put spaces in commandline arguments or use quotes\n"
    " NO: --CONNECT:Endpoint=[NAME=svc, PORT=4711]\n"
    " OK: --CONNECT:Endpoint=\"[NAME=svc, PORT=4711]\"\n"
    "\n"
    "\n"
    ;
  return _ret;
}

int
iifApp::run ( int argc, char* argv[] )
{
    E_LOG("iifApp::run ~ Running");
  std::string ddname = "L_AOmode"; // asked via getDouble
  lbto::DDstruct ddt;
  lbto::SeqDD dd;
  lbto::SeqPos2 stars, refs;
  lbto::result res;
  // Ltcs::IifServiceWorkerInterfacePtr iif;
  std::string endPointName = "CONNECT";
  std::string serviceName = "IIF.SVC";// "Factory";
  
  
  U1_LOG(config()->leaf("CONNECT"));

  lbto::position2 reference = {
    "SIDEREAL",
    0.009,
    0.01,
    "RADEC",
    2000.0,
    "J2000",
    0.0,
    0.0,
    0.0,
    "U",
    0.0,
    "U_B",
    0.8,
    "",
    0,
    0,
    0
  };
  refs.push_back(reference);
  if(config()->getAtNode<Nice::Endpoint>(endPointName) != Nice::Endpoint())
   {
      try
        {
          I_LOG("Trying")
          // NOTE: IIF
          Nice::Endpoint p = config()->getAtNode<Nice::Endpoint>(endPointName);
          // Nice::Endpoint p = Nice::Endpoint::fromString("[NAME=ltcs.iif-svr,TCP=localhost:10000,TIMEOUT=10]");
          I_LOG("Trying2");
          Nice::AppConfigClientPtr con = Nice::AppConfigClient::create(p, config()->node("DATA"));
          I_LOG("Trying3");
          m_iif = Ltcs::IifServiceWorkerInterface::create(config()->node("DATA."+serviceName));
          U3_LOG("> Service Name :" << m_iif->readServiceName());

          U3_LOG(argc);
          for (int ii=0; ii<argc; ii++)
            {
              U3_LOG(argv[ii])
                }

          if (argc > 3)
            {
              std::string str;
              for (int i = 3; i < argc; i++)
                {
                  str = argv[i];
                  U3_LOG(argv[i]);
                  if ( str.substr ( 0, 2 ) == "--" )
                    {
                      if (str.substr(2) == "authorize")
                        {
                          U3_LOG("Going to ask if LBTI is authorized ... ");
                          res = m_iif->iifAuthorize();
                          U3_LOG("Asked");
                          if (!res.rescode)
                            {
                              U8_LOG("Test of new parameter passed")
                                // return EXIT_SUCCESS;
                                }
                          else {return EXIT_FAILURE;}
                        }
                    }
                }
            }



          U3_LOG("> Is reachable :" << m_iif->isReachable());
          I_LOG("> RA           :" << m_iif->getRA());
          I_LOG("> DEC          :" << m_iif->getDEC());
          I_LOG("> " << ddname << "     :" << m_iif->getDouble(ddname, "log"));

          ddt.DDname = "L_Instrument";
          dd.push_back(ddt);
          ddt.DDname = "L_AOmode";
          dd.push_back(ddt);
          ddt.DDname = "L_AOShape";
          dd.push_back(ddt);
          ddt.DDname = "L_AOStatus";
          dd.push_back(ddt);
          ddt.DDname = "L_AOaoReady";
          dd.push_back(ddt);
          res = m_iif->iifGetParameter(dd);


          I_LOG("> iifGetParameter :" << m_iif->iifGetParameter(dd));
          I_LOG(res.resmsg);
          I_LOG("> getLINCstation  :" << m_iif->getLINCstation());
          // I_LOG(m_iif->readPosition());
          I_LOG("> PA           :" << m_iif->getParallacticAngle());
          I_LOG("> UTC          :" << m_iif->getUTC());
          I_LOG("> LST          :" << m_iif->getLST());
          // I_LOG("> Hour Angle   :" << m_iif->getHourAngle());
          I_LOG(m_iif->iifAuthorize()); // instrument authorized on service startup
          // I_LOG(m_iif->iifAuthorizeGet()); // instrument authorized on service startup

          lbto::position2 target = {"SIDEREAL", //object type
                    3.399,      // RA or AZ (radian)
                    1.0009,     // DEC or ALT (radian)
                    "RADEC",    // "RADEC", "AZALT"
                    2000.0,     // epoch (year)
                    "J2000",    // equinox "J2000"
                    0,          // proper motion dRA/dt cos(DEC) (radian/yr)
                    0,          // proper motion dDEC/dt (radian/yr)
                    0,          // magnitude
                    "U",        // filter name
                    0,          // color index
                    "U_B",      // color type
                    0.8,        // wavelength (microns)
                    "",         // non-sidereal ephemeris file name
                    0,          // DIFFERENTIAL MJD (UT days)
                    0,          // DIFFERENTIAL dRA/dt * cos(DEC) (radian/day)
                    0           // DIFFERENTIAL dDEC/dt (radian/day)
          };

          lbto::position2 guideStar = {"SIDEREAL", //object type
                       1.399,      // RA or AZ (radian)
                       1.0009,     // DEC or ALT (radian)
                       "RADEC",    // "RADEC", "AZALT"
                       2000.0,     // epoch (year)
                       "J2000",    // equinox "J2000"
                       0,          // proper motion dRA/dt cos(DEC) (radian/yr)
                       0,          // proper motion dDEC/dt (radian/yr)
                       0,          // magnitude
                       "U",        // filter name
                       0,          // color index
                       "U_B",      // color type
                       0.4,        // wavelength (microns)
                       "",         // non-sidereal ephemeris file name
                       0,          // DIFFERENTIAL MJD (UT days)
                       0,          // DIFFERENTIAL dRA/dt * cos(DEC) (radian/day)
                       0           // DIFFERENTIAL dDEC/dt (radian/day)
          };

          stars.push_back(target);
          stars.push_back(guideStar); // guide star MUST be specified before preset

          // I_LOG(m_iif->iifSetStars2(stars));
          // if (res.rescode == EXIT_SUCCESS)
          //   I_LOG(res.rescode);
          // I_LOG(m_iif->iifSetReference2(refs)); // AO reference star
          // //stars = m_iif->getPresetStars();
          // //I_LOG("> getPresetStars :" << pos.size());
          // I_LOG("> iifPresetTelescopeStart :" << m_iif->iifPresetTelescopeStart(0.0,                 // rotator angle
          //                                                                      "IDLE",              // rotator mode
          //                                                                      "ADAPTIVEACE_TRACK", // telescope mode
          //                                                                      "left"               // side
          //                                                                      ));
          // I_LOG("> iifPresetTelescopeWait: " << m_iif->iifPresetTelescopeWait());
          // I_LOG(m_iif->setPresetTelescopeGet());
          I_LOG("> Alt          :" << m_iif->getAlt());
          I_LOG("> AZ           :" << m_iif->getAz());
          I_LOG("> Epoch        :" << m_iif->getEpoch());
          I_LOG("> RA  Radians  :" << m_iif->getRAradians());
          I_LOG("> DEC Radians  :" << m_iif->getDECradians());
          // I_LOG(m_iif->setOffsetPointing(double _offx, double _offy, std::string __coordsys, std::string __move_type, std::string __side));
          // I_LOG(m_iif->getRotatorPolynomials(double __starttime, int __count, double __interval, int __order, std::string __side));
          // I_LOG(m_iif->getKFPCoordinates(std::string __side));
          // I_LOG("> Preset stars :" << m_iif->getPresetStars());
          // I_LOG("> RunAO        :" << m_iif->iifRunAO("NORMAL", // TYPE: Issues an AcquireRefAO without rePoint followed by a StartAO.
          //                                            "left" // side
          //                                            ))
          I_LOG("> is slewing   :" << m_iif->isSlewing());
          Nice::SeqSeqDouble traj;
          double trajStartTime = Nice::Date::now().toMJD();
          double trajInterval = 60; // seconds
          int trajPolyCount = 120;  // number of polynomials
          int trajPolyOrder = 2;
          std::string side = "left";

          // traj = m_iif->getRotatorPolynomials(trajStartTime, trajPolyCount, trajInterval, trajPolyOrder, side);
          // I_LOG(traj);
          // writeTrajOnFile(traj);

          // I_LOG("> MoveXY       :" << m_iif->iifMoveXY(1.000,-0.810,"M1","left")); // 
        }
      catch (const Nice::Exception & ex)
        {
          I_LOG("Exception!!");
          E_LOG(ex);
          return 1;
        }
   }
  return 0;
}


void iifApp::interruptCallback( int _sig)
{
  E_LOG("Interrupt #" << _sig);
}

// void iifApp::interruptCallback(int _sig)
// {
//   N_LOG( "Interrupt #" << _sig);
//   //    Basda::ServiceWorkerInterface::terminateAll( );
// }


int iifApp::writeTrajOnFile(const Nice::SeqSeqDouble &_trajSet)
{
    E_LOG("iifApp::" << __FUNCTION__ << " ~ called");
  std::ofstream trajLog;
  trajLog.open("traj_log.dat");
  if (!trajLog)
    {
      E_LOG("Cannot open out file for trajcetory log!");
      return 1;
    }
  trajLog.precision(6);
  for (BOOST_AUTO(itTraj,_trajSet.begin()); itTraj < _trajSet.end(); ++itTraj)
    {
      for (BOOST_AUTO(it, itTraj->begin()); it < itTraj->end(); ++it)
        {
          trajLog.precision(6);
          trajLog << std::fixed << *it << '\t';
        }
      trajLog << std::endl;
    }
  trajLog.close();
  return 0;
}





// int main(int argc, char* argv[])
// {
//   std::cout << "> The following command is working." << std::endl;
//   std::cout << "./iifApp --CONNECT:Endpoint=[NAME=ltcs.iif-svr,TCP=localhost:10000,TIMEOUT=10] --LOGGER.LEVEL:LogLevel=DEBUG $* " << std::endl;

//   iifApp app(argc,argv);
//   std::cout << "ERROR1" << std::endl;
//   // Basda::MoccaWheelServiceWorkerInterfacePtr coro_slit_u = app.connect<Basda::MoccaWheelServiceWorkerInterface>("coro_w-DUMMY");
//   // std::cout << "ERROR2" << std::endl;
//   Ltcs::IifServiceWorkerInterfacePtr iif = app.connect<Ltcs::IifServiceWorkerInterface>("ltcs.iif-svr.IIF");
//   std::cout << "ERROR3" << std::endl;
//   U6_LOG(iif->iifAuthorize());
//   app.start(argc, argv);
// }
