#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "instr_hosts.h"

static char *getItem(char *line, char *name, char *value, int value_len) {
  char find[32];
  char *found, *sp, *result;
  int l;
  
  snprintf(find, sizeof find, "%s=%s", name, value);
  found = strstr(line, find);
  if (found && *value != '\0' && found[strlen(find)] > ' ' && found[strlen(find)] != '.') {
    /* when value is given, it must be complete, (a dot or a space terminates the value) */
    found = NULL;
  }
  if (found) {
    found += strlen(name)+1;
    if (value_len == 0) {
      result = found;
    } else {
      sp = strchr(found, ' ');
      if (sp && sp < found + value_len) {
        l = sp - found;
      } else {
        l = strlen(found);
      }
      if (l < value_len) {
        strncpy(value, found, l);
        value[l] = '\0';
        result = value;
      } else {
        value[0] = '\0';
        result = NULL;
      }
    }
  } else {
    if (value_len > 0) {
      *value = '\0';
    }
    result = NULL;
  }
  return result;
}

void scanHostList(void (*func)(char *)) {
  int i;
  FILE *fil, *lfil;
  char *hostlist;
  char localhostlist[512];
  char line[512], lline[512];
  int dirty;
  
  hostlist = getenv("InstrumentHostList");
  if (!hostlist) {
    hostlist="/afs/psi.ch/project/sinq/common/lib/sea/hostlist";
  }
  fil = fopen(hostlist, "r");
  snprintf(localhostlist, sizeof localhostlist, "%s/.six/hostlist", getenv("HOME"));
  lfil = fopen(localhostlist, "r");
  dirty = 0;
  if (fil) {
    if (!lfil) dirty = 1;
  } else {
    if (!lfil) return;
    fil = lfil;
    lfil = NULL;
  }
  while (NULL != fgets(line, sizeof line, fil)) {
    if (!dirty && lfil
               && (fgets(lline, sizeof lline, lfil) == NULL
                   || strcmp(line, lline) != 0)) {
      dirty = 1;
    }
    if (line[0] != '#') {
      func(line);
    }
  }
  if (fil) fclose(fil);
  if (lfil) fclose(lfil);
  if (dirty) {
    fil = fopen(hostlist, "r");
    if (fil) {
      lfil = fopen(localhostlist, "w");
      if (lfil) {
        while( EOF != (i = getc(fil)) ) { /* copy file to local file */ 
          putc(i, lfil); 
        }
        fclose(lfil);
      }
      fclose(fil);
    }
  }
}

static char *service;
static char *crit;
static char *input;
static int finished;
static int home;
static char hostport[128];
static char *instr;
static int instr_len;
static char *host;
static int host_len;
static int port;

void findCrit(char *line) {
  char *colon;
  int i;
  
  if (getItem(line, crit, input, 0) != NULL) {
    hostport[0]='\0';
    if (getItem(line, service, hostport, sizeof hostport) != NULL) {
      instr[0] = '\0';
      if (finished == 0) {
        getItem(line, "instr", instr, instr_len);
      }
      colon = strchr(hostport, ':');
      if (colon) {
        i = atoi(colon+1);
        if (i > 0) {
          *colon='\0';
          if (finished == 0) {
            snprintf(host, host_len, "%s", hostport);
            port = i;
          }
          finished++;
          if (getItem(line, "host", getenv("HOST"), 0) != NULL) {
            home = 1;
          }
        }
      }
    }
  }
}

int InstrHost(char *serviceArg, char *inputArg, char *instrArg, int instr_lenArg,
              char *hostArg, int host_lenArg, int *portArg) {
  service = serviceArg;
  input = inputArg;
  instr = instrArg;
  instr_len = instr_lenArg;
  host = hostArg;
  host_len = host_lenArg;
  port = 0;
  home = 0;
  finished = 0;
  
  if (input == NULL || input[0] <= ' ') {
    crit = "host";
    input = getenv("HOST");
  } else {
    crit = "instr";
  }

  scanHostList(findCrit);
  
  *portArg = port;
  return home * finished;
}

static char *list;
static int list_len;

void listInstr(char *line) {
  int l;
  *list='\0';
  if (getItem(line, service, "", 0) &&
      getItem(line, "instr", list, list_len)) {
    l = strlen(list);
    list += l;
    list_len -= l;
  } else if (line[0] > ' ') {
    return;
  }
  if (list_len > 0) {
    *list = ' ';
    list++;
    list_len--;
  }
}

void InstrList(char *serviceArg, char *listArg, int list_lenArg) {
  service = serviceArg;
  list = listArg;
  list_len = list_lenArg;
  scanHostList(listInstr);
  if (list > listArg) list--; /* remove trailing blank */
  *list = '\0';
}

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

#include "myc_fortran.h"

int F_FUN(instr_host)(F_CHAR(service), F_CHAR(input), F_CHAR(instr), F_CHAR(host), int *port
                     , int service_len, int input_len, int instr_len, int host_len) {
  char buf[256], in[256], ho[256], sv[256];
  int iRet;

  STR_TO_C(sv, service);
  STR_TO_C(buf, input);
  iRet=InstrHost(sv, buf, in, sizeof(in), ho, sizeof(ho), port);
  if (*port>0) {
    STR_TO_F(instr, in);
    STR_TO_F(host, ho);
  }
  return iRet;
}

#endif
