#include <stdlib.h>
#include <string.h>
#include "sys_util.h"
#include "err_handling.h"
#include "str_util.h"
#include "tecs_cli.h"

static char device[80], command[80];
static int readTemp, configuring;
static float tempX, tempP, tempC;

pTecsClient TeccInit(char *startcmd, int port) {
  CocConn *conn;

  NEW(conn);
  if (startcmd[0]=='#') {
    ERR_I(CocInitClient(conn, startcmd+1, port, "#rwacs", 0, ""));
  } else {
    ERR_I(CocInitClient(conn, "", port, "#rwacs", 0, startcmd));
  }
  CocDefFlt(tempC, CocRD);
  CocDefFlt(tempP, CocRD);
  CocDefFlt(tempX, CocRD);
  CocDefStr(device, CocWR);
  CocDefInt(configuring, CocRD);
  CocDefInt(readTemp, CocWR);
  CocDefCmd(command);

  return((pTecsClient)conn);
  OnError: return(NULL);
}

int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) {
  readTemp=1;
  ERR_I(CocCmd(conn, "tempC,tempX,tempP,[readTemp],configuring"));
  *tC=tempC;
  *tX=tempX;
  *tP=tempP;
  return(configuring);
  OnError: return(-1);
}

int TeccGet(pTecsClient conn, float *temp) {
  readTemp=1;
  ERR_I(CocCmd(conn, "tempP,[readTemp],configuring"));
  *temp=tempP;
  return(configuring);
  OnError: return(-1);
}

int TeccWait(pTecsClient conn) {
  int last, cnt;

  last=0;
  cnt=0;
  do {
    CocDelay(250);
    ERR_I(CocCmd(conn, "configuring"));  
    if (configuring==last || configuring>1000) {
      cnt++;
      if (cnt>20) ERR_MSG("configuring timeout");
    } else {
      cnt=0;
      last=configuring;
    }
  } while (configuring>0);
  return(0);
  OnError: return(-1);
}

int TeccSet(pTecsClient conn, float temp) {
  tempC=temp;
  ERR_I(CocCmd(conn, "[tempC]"));
  return(0);
  OnError: return(-1);
}

int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
  char *res;
  int cnt;

  str_copy(command, cmd);
  ERR_I(CocCmd(conn, "[$]"));
  cnt=40;
  CocDelay(100);
  while (cnt>0) {
    ERR_I(CocCmd(conn, "$"));
    if (command[0]!='\0') {
      str_ncpy(reply, command, replyLen);
      return(0);
    }
    CocDelay(250);
    cnt--;
  }
  str_ncpy(reply, "<no response>", replyLen);
  return(0);
  OnError: return(-1);
}

int TeccQuitServer(pTecsClient conn) {
  int iret, cnt;

  ERR_I(iret=CocCheck(conn));
  if (iret==0) {
    ERR_I(CocSet(conn, "quit", "1"));
    cnt=50;
    while (iret==0 && cnt>0) {
      CocDelay(100);
      ERR_I(iret=CocCheck(conn));
      cnt--;
    }
  }
  if (iret==1) return(0);
  ERR_MSG("Does not quit within 5 seconds");
  OnError:
    return(-1);
}

void TeccClose(pTecsClient conn) {
  if (conn!=NULL) {
    CocCloseClient(conn);
    FREE(conn);
  }
}

/* fortran wrappers --------------------------------------------------

  reduced functionality:
  connection is static, so only one connection at a time may be opened 

*/

#ifdef F_CHAR
/* compile only when fortran c interface stuff is defined */


#ifdef __VMS
#define tecs_get_par_ tecs_get_par
#define tecs_set_par_ tecs_set_par
#define tecs_send_ tecs_send
#define tecs_init_ tecs_init
#define tecs_get3_ tecs_get3
#define tecs_set_ tecs_set
#define tecs_wait_ tecs_wait
#define tecs_is_open_ tecs_is_open
#define tecs_close_ tecs_close
#define tecs_quit_server_ tecs_quit_server
#endif

static pTecsClient conn=NULL;

int tecs_set_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) {
  char nbuf[64], pbuf[256];
  int iret=-1;

  STR_TO_C(nbuf, name);
  STR_TO_C(pbuf, par);

  ERR_I(iret=CocSet(conn, nbuf, pbuf));

  return(0);
  OnError: return(iret);
}

int tecs_get_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) {
  char nbuf[64], pbuf[256];
  int iret=-1;

  STR_TO_C(nbuf, name);
  ERR_I(iret=CocGet(conn, nbuf, pbuf));
  return(STR_TO_F(par, pbuf));
  OnError: return(iret);
}

int tecs_send_(F_CHAR(cmd), F_CHAR(reply), int cmd_len, int reply_len) {
  char cbuf[80], rbuf[80];

  STR_TO_C(cbuf, cmd);
  ERR_I(TeccSend(conn, cbuf, rbuf, sizeof(rbuf)));
  return(STR_TO_F(reply, rbuf));
  OnError: return(-1);
}

int tecs_init_(F_CHAR(startcmd), int *port, int startcmd_len) {
  char sbuf[132];

  STR_TO_C(sbuf, startcmd);
  ERR_P(conn=TeccInit(sbuf, *port));
  return(0);
  OnError: return(-1);  
}

int tecs_get_(float *temp) {
  return(TeccGet(conn, temp));
}

int tecs_get3_(float *t1, float *t2, float *t3) {
  return(TeccGet3(conn, t1, t2, t3));
}

int tecs_set_(float *temp) {
  return(TeccSet(conn, *temp));
}

int tecs_wait_(void) {
  return(TeccWait(conn));
}

int tecs_is_open_() {
  return(conn!=NULL);
}

void tecs_close_(void) {
  TeccClose(conn);
  conn=NULL;
}

int tecs_quit_server_(void) {
  return(TeccQuitServer(conn));
}

#endif
