#include <stdlib.h>

#include <string.h>
#include "rs232c_def.h"
#include "asynsrv_def.h"
#include "sinq_prototypes.h"
#include "sys_util.h"
#include "err_handling.h"
#include "tecs_serial.h"
#include "coc_logfile.h"
#include "str_util.h"

#define A_CHK(R) if (1!=(R)) { SerA_error(); ErrTxt(#R,0); goto OnError; }

void (*idleHandler)(int,int);

struct SerChan {
  struct AsynSrv__info    asyn_info; /* Contains skt, host, port & chan */
  struct RS__MsgStruct    to_host;
  struct RS__RespStruct   from_host;
  char cmd[SER_BUF_LEN];
};

void SerA_error(void) {
  char *a_txt;
  int a_cod, a_my, a_vms;

  AsynSrv_ErrInfo(&a_txt, &a_cod, &a_my, &a_vms);
  ErrMsg("asynsrv error"); ErrTxt(a_txt,0);
}

SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)) {
  struct SerChan *ser;
  char hbuf[64], cport[16];
  char *p, *c;
  int port, chan;

  idleHandler=idleHdl;
  NEW(ser);
  str_copy(hbuf, host);
  p=str_split(ser->asyn_info.host, hbuf, ':');
  port=4000;
  chan=0;
  if (p!=NULL) {
    c=str_split(cport, p, '/');
    if (c!=NULL) chan=atoi(c);
    port=atoi(cport);
  }
  ser->asyn_info.port=port;
  ser->asyn_info.chan=chan;
  logfileOut(LOG_MAIN, "open connection to %s:%d/%d\n", ser->asyn_info.host, ser->asyn_info.port, ser->asyn_info.chan);
  A_CHK(AsynSrv_Open(&ser->asyn_info));
  if (msecTmo==0) msecTmo=5000;
  A_CHK(AsynSrv_Config(&ser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL));
  return((SerChannel *)ser);
  OnError: return(NULL);
}

int SerClose(SerChannel *serch) {
  struct SerChan *ser;

  ser=(struct SerChan *)serch;
  A_CHK(AsynSrv_Close(&ser->asyn_info, 0));
  return(0);
  OnError: return(-1);
}

char *SerCmdC(SerChannel *serch, const char *cmnd) {
  char cmd[SER_BUF_LEN];
  int l;

  l=strlen(cmnd);
  if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);
  strcpy(cmd, cmnd);
  return(SerCmd(serch, cmd));
  OnError: return(NULL);
}

char *SerCmd(SerChannel *serch, char *cmnd) {
  int l;
  struct SerChan *ser;
  char *result;

  l=strlen(cmnd);
  if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);

  ser=(struct SerChan *)serch;
  logfileOut(LOG_SER, ">%s\n", cmnd);
  cmnd[l]=ser->asyn_info.eot[1];
  cmnd[l+1]='\0';
  A_CHK(AsynSrv_SendCmnds(&ser->asyn_info, &ser->to_host, &ser->from_host, cmnd, NULL));
  result=AsynSrv_GetReply(&ser->asyn_info, &ser->from_host, NULL);
  if (result==NULL) ERR_MSG("empty result");
  /* if (idleHandler!=NULL) idleHandler(50,0); */
  logfileOut(LOG_SER, "<%s\n", result);
  return(result);
  OnError: return(NULL);
}
