/*
 * $id$
 */

#include "SerialPythonServerClient.hh"
//#include <time.h>

#ifdef _MSC_VER

int nanosleep(const struct timespec *req, struct timespec *rem)
{
  DWORD mSec = 0;
  mSec += (DWORD)(req->tv_sec) * 1000; /* sec -> msec */
  mSec += (DWORD)(req->tv_nsec) / 1000000; /* nsec -> msec */

  Sleep(mSec);
  return 0;
};

#endif
bool SerialPythonServerClient::Start(const std::vector<std::string> &s,
  const UInt4 umax) {

  const bool neverTimeout = (umax==0) ? true : false;
  const unsigned long intval = 50000000l;        // 50 m sec (5e7 n sec)
  unsigned long retrymax = ((umax*1000000l)/intval)+1;

  // first connection to the remotehost
  class ASIO_local *_Al
    = new ASIO_local(remhost, remport);
  while ((!_Al->stat()) && ((retrymax>0) || neverTimeout)) {
    struct timespec r1, r2;
    r1.tv_sec = 0;
    r1.tv_nsec= intval;
    if (!neverTimeout)
      if (--retrymax==0) r1.tv_nsec = (umax*1000000l) % intval;
    nanosleep(&r1, &r2);

    if (_Al!=NULL) delete _Al;
    _Al    = new ASIO_local(remhost, remport);
  };
  if ((!_Al->stat()) && (retrymax==0)) {
    delete _Al;
    std::cerr << "giving up the 1st connection to the SerialPythonServer" << std::endl;
    return false;
  }

  *(_Al->h) >> new_port >> key;
  //new_port = _SNE.ReceiveUInt4();
  //key      = _SNE.ReceiveUInt4();

  class SerialNeutronExchanger _SNE(*_Al);
  _SNE.Transmit(s);

  delete _Al;

  //sleep(1);
  //std::cerr << new_port << "," << key << std::endl;

  retrymax = ((umax*1000000l)/intval)+1;
  do {
    struct timespec r1, r2;
    r1.tv_sec = 0;
    r1.tv_nsec= intval;
    if (!neverTimeout)
      if (--retrymax==0) r1.tv_nsec = (umax*1000000l) % intval;
    nanosleep(&r1, &r2);
//    std::cerr << "." << std::flush;

    if (Al!=NULL) delete Al;
  // create second connection
    Al  = new ASIO_local(remhost, boost::lexical_cast<std::string>(new_port));
    if (!Al->stat()) {
      //std::cerr << "2nd SNE stream bad" << std::endl;
    }
  } while ((!Al->stat()) && ((retrymax>0) || neverTimeout));
  if ((!Al->stat()) && (retrymax==0)) {
    delete Al;
    std::cerr << "giving up the 2nd connection to remote python process" << std::endl;
    return false;
  }

  SNE = new SerialNeutronExchanger(*Al);

  SNE->Transmit(key);

  return true;
}

SerialNeutronExchanger & SerialPythonServerClient::refSNE(void) const {
  return *SNE;
}
