/* Copyright 1993 by gregg hanna */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifdef NO_X
#include <ctype.h>
#include <strings.h>
#else
#include <X11/Xos.h>
#endif

#include "patchlevel.h"
#include "rolo.h"
#include "roloP.h"
#include "compat.h"

#define EXPSIZE 1024

RoloRec *RoloList = NULL;
static char *rolofile = NULL;
int verbose = 0;
int RoloSearch[4] = {1,1,1,1};
int selectFilter = 0;

#include "myregexp.h"

int NumRoloOn()
{
  RoloRec *rr;
  int n;

  for ( n = 0, rr = RoloList; rr != NULL; rr = rr->next )
    if ( rr->on ) n++;
  return n;
}

#ifndef NO_TIME
static char *CheckField(field)
     char *field;
{
  char *s, *t , *r, *buf;
  time_t time_val;
  int i;

  if ( field == NULL ) return field;
  if ( mystrncasecmp(field,"as of:",6) == 0 )
    r = field;
  else {
    r = mystrstrcase(field,"\nas of:");
    if (r) r++; /* skip nl */
  }
  if (r) {
    buf = (char*)malloc(strlen(field)+30);  /* allocate bigger buffer */
    /* copy text up to & including AS OF marker into buffer */
    for ( t = buf, s = field; s != r; t++, s++ )
      *t = *s;
    for ( i = 0; i < 6; i++, t++, s++ )
      *t = *s;
    for ( ; *s == ' ' || *s == '\t'; t++, s++ )
      *t = *s;
    *t = '\0';
    /* write new AS OF entry into buffer */
    time_val = time((time_t*)NULL);
    sprintf(t,"%s",ctime(&time_val));
    /* skip to eol in old & new string (i.e. skip old AS OF line) */
    while ( *s != '\n' && *s != '\0' ) s++;
    if (*s=='\n') s++;
    while ( *t != '\n' && *t != '\0' ) t++;
    if (*t=='\n') t++;
    /* copy rest of buffer */
    /*strcat(t,s);*/
    mystrcpy(t,s);
    return buf;
  }
  return field;
}
#endif

void MakeNewRolo(name,number,number2,text,checkfield)
     char *name, *number, *number2, *text;
     int checkfield;
{
  RoloRec *rr, *pp;
  char *s;

  rr = (RoloRec*)malloc(sizeof(RoloRec));

  rr->next = NULL;

  rr->name = mystrdup(name);
  s = index(rr->name,'\n');
  if ( s != NULL ) *s = '\0';

  if (number[0]) {
    rr->number = mystrdup(number);
    s = index(rr->number,'\n');
    if ( s != NULL ) *s = '\0';
  } else {
    rr->number = mystrdup("xxx-yyyy");
    rr->number[0] = '\0';
  } 
  if (number2[0]) {
    rr->number2 = mystrdup(number2);
    s = index(rr->number2,'\n');
    if ( s != NULL ) *s = '\0';
  } else {
    rr->number2 = mystrdup("xxx-yyyy");
    rr->number2[0] = '\0';
  } 

#ifndef NO_TIME
  if ( checkfield )
    rr->text = CheckField(mystrdup(text));
  else
#endif
    rr->text = mystrdup(text);

  rr->on = 1;

  if ( RoloList == NULL ) RoloList = rr;
  else if ( mystrcasecmp(RoloList->name,rr->name) > 0 ) {
    rr->next = RoloList;
    RoloList = rr;
  } else {
    for ( pp = RoloList; pp->next != NULL; pp = pp->next )
      if ( mystrcasecmp(pp->next->name,rr->name) > 0 ) break;
    rr->next = pp->next;
    pp->next = rr;
  }
}

#ifndef ROLOFILENAME
#ifdef VMS
#define ROLOFILENAME "rolo-file"
#else
#define ROLOFILENAME ".rolo"
#endif
#endif

void InitRolo(argc,argv,stop)
     int argc;
     char *argv[];
     int stop;
{
  int c;
  extern char *optarg;
  FILE *f;

  rolofile = getenv("ROLODEX");
  if ( rolofile == NULL ) {
    rolofile = getenv("HOME");
    if ( rolofile == NULL ) rolofile = ROLOFILENAME;
    else {
      rolofile = (char*)malloc(512);
#ifndef VMS
      sprintf(rolofile,"%s/%s",getenv("HOME"),ROLOFILENAME);
#else
      sprintf(rolofile,"%s%s",getenv("HOME"),ROLOFILENAME);
#endif
    }
  }

  verbose = 0;
  while ((c = getopt(argc, argv, "sf:hv")) != -1) {
    switch (c) {
    case 's':
      selectFilter = 1;
      break;
    case 'f':
      rolofile = optarg;
      break;
    case 'v':
      verbose = 1;
      break;
    case 'h':
    case '?':
    default:
      if (!stop) break;
      fprintf(stderr,"usage:  %s [-v] [-f rolodexfile]\n",argv[0]);
      exit(1);
      break;
    }
  }
  if (verbose)
    fprintf(stderr,"%s Version %d.%d Patch Level %d\n",argv[0],VERSION_MAJOR,VERSION_MINOR,PATCHLEVEL);
  f = fopen(rolofile,"r");
  if ( f == NULL ) {
    if (verbose) fprintf(stderr,"Creating new rolodex file %s\n",rolofile);
    f = fopen(rolofile,"w");
  }
  fclose(f);
}

void SetupRolo()
{
  char firstname[STRSIZE], lastname[STRSIZE], name[STRSIZE];
  char homephone[STRSIZE], workphone[STRSIZE], rest[STRSIZE];
  char tempstring[STRSIZE], *s;

  FILE *f;
  int c, sep;

  f = fopen(rolofile,"r");
  if ( f == NULL ) {
    perror(rolofile);
    exit(1);
  }

  firstname[0] = lastname[0] = '\0';
  homephone[0] = workphone[0] = rest[0] = '\0';

  while (!feof(f)) {

    fgets(tempstring, STRSIZE,f);
    (s = strchr(tempstring, '\n')) && (*s = '\0'); /* strip newline */
    if (strncasecmp(tempstring, "firstname:", 10) == 0) {
      for (s = &tempstring[10]; *s == ' '; s++) { };
      strcpy(firstname, s);
    } else
      if (strncasecmp(tempstring, "lastname:", 9) == 0) {
	for (s = &tempstring[9]; *s == ' '; s++) { };
	strcpy(lastname, s);
      } else
	if (strncasecmp(tempstring, "homephone:", 10) == 0) {
	  for (s = &tempstring[10]; *s == ' '; s++) { };
	  strcpy(homephone, s);
	} else
	  if (strncasecmp(tempstring, "workphone:", 10) == 0) {
	    for (s = &tempstring[10]; *s == ' '; s++) { };
	    strcpy(workphone, s);
	  } else
	    if (strncmp(tempstring, "----", 4) == 0) {
	      strcpy(name, lastname);
	      strcat(name, ", ");
	      strcat(name, firstname);
	      /* printf("%s ", name); */
	      if (firstname[0] || lastname[0])
		MakeNewRolo(name,homephone,workphone,rest,0);
	      firstname[0] = lastname[0] = '\0';
	      homephone[0] = workphone[0] = rest[0] = '\0';
	    }
	    else {
	      strcat (tempstring, "\n");
	      strcat (rest, tempstring);
	    }
  }
  fclose(f);
}

void DeleteRoloCard(n)
     int n;
{
  RoloRec *rr, *pp;

  if ( n < 0 ) return;

  rr = GetN(n);
  if ( rr == RoloList ) RoloList = RoloList->next;
  else {
    for ( pp = RoloList; pp->next != rr; pp = pp->next );
    pp->next = rr->next;
  }
  if (rr->name != NULL)   free(rr->name);
  if (rr->number != NULL) free(rr->number);
  if (rr->number2 != NULL) free(rr->number2);
  if (rr->text != NULL)   free(rr->text);
  free((char*)rr);
}

int backedUp = 0;

void Backup()
{
  char bakfile[STRSIZE], buf[10240];
  FILE *in, *out;
  int n;

  sprintf(bakfile, "%s-", rolofile);
  if (verbose)
    fprintf(stderr,"Backing up '%s' to '%s'.\n",rolofile,bakfile);

  if ((in = fopen(rolofile, "r")) == NULL) {
    if (errno != ENOENT) {
      perror(rolofile);
      exit(1);
    }
  } else if ((out = fopen(bakfile, "w")) == NULL) {
    perror(bakfile);
    fprintf(stderr,"Unable to create backup rolodex file.\n");
    fclose(in);
  } else {
    while ((n = fread(buf, 1, 10240, in)) > 0) 
      fwrite(buf, 1, n, out);

    fclose(in);
    fclose(out);
  }

  backedUp = 1;
}

void WriteRolo()
{
  FILE *f;
  char  *s;
  RoloRec *rr;

  if ( ! backedUp ) Backup();

  f = fopen(rolofile,"w");
  if ( f == NULL ) {
    perror("WriteRolo");
    fprintf(stderr,"An error occured while trying to write your\n");
    fprintf(stderr,"rolodex file.  The attempt is being aborted\n");
    fprintf(stderr,"so your most recent changes might not be saved.\n");
    fprintf(stderr,"The error occurred while attempting to open the\n");
    fprintf(stderr,"file %s for writing.\n",rolofile);
    return;
  }

  for ( rr = RoloList; rr != NULL; rr = rr->next ) {
    /* write data */
    if ( rr->name && rr->name[0]) {
      s = strchr(rr->name,',');
      if (s) {
	*s = '\0';
	fprintf(f,"Lastname: %s\n", rr->name);
	*s = ',';
	for (s++; *s == ' '; s++) { };
	fprintf(f,"Firstname: %s\n", s);
      } else
	fprintf(f,"Lastname: %s\n",rr->name);
    } else continue;
    if ( rr->number ) fprintf(f,"Homephone: %s\n",rr->number);
    if ( rr->number2 ) fprintf(f,"Workphone: %s\n",rr->number2);
    if ( rr->text ) fprintf(f,"%s",rr->text);
    /* do new-line check to make xrolo happy */
    for ( s = &rr->text[strlen(rr->text)-1]; *s == ' ' || *s == '\t'; s-- );
    if ( *s != '\n' ) fputc('\n',f);
    fprintf(f, "----\n");
  }
  fclose(f);
}

int GetIndex(s)
     char *s;
{
  RoloRec *rr;
  int n;

  for ( rr = RoloList, n = 0; rr != NULL; rr = rr->next, n++ )
    if ( rr->on && mystrcasecmp(rr->name,s) >= 0 ) break;

  return n;
}

RoloRec *GetN(n)
     int n;
{
  RoloRec *rr;

  for ( rr = RoloList; rr != NULL && ! rr->on; rr = rr->next );
  for ( ; rr != NULL; rr = rr->next ) {
    if ( rr->on ) n--;
    if ( n < 0 ) break;
  }
  return rr;
}

char *GetCardName(n)
     int n;
{
  RoloRec *rr;
  rr = GetN(n);
  return (rr?rr->name:NULL);
}

char *GetNumber(n)
     int n;
{
  RoloRec *rr;
  rr = GetN(n);
  return (rr?rr->number:NULL);
}

char *GetNumber2(n)
     int n;
{
  RoloRec *rr;
  rr = GetN(n);
  return (rr?rr->number2:NULL);
}

char *GetText(n)
     int n;
{
  RoloRec *rr;
  rr = GetN(n);
  return (rr?rr->text:NULL);
}

static int AllSpace(s)
     char *s;
{
  for ( ; *s != '\0'; s++)
    if ( ! isspace(*s) ) return 0;
  return 1;
}

void RoloFilter(s)
     char *s;
{
  RoloRec *rr;
  char expbuf[EXPSIZE], *t;

  if ( s == NULL || AllSpace(s) )
    for ( rr = RoloList; rr != NULL; rr = rr->next )
      rr->on = 1;
  else {
#ifndef DONT_REGEXP
    if ( s[0] == '\\' ) {
      s++;
      t = re_comp(s);
      if ( t != NULL ) { if ( verbose ) fprintf(stderr,"%s\n",t); }
      else
	for ( rr = RoloList; rr != NULL; rr = rr->next )
	  rr->on = ( (rr->name && re_exec(rr->name) && RoloSearch[0]) ||
		     (rr->number && re_exec(rr->number) && RoloSearch[1]) ||
		     (rr->number2 && re_exec(rr->number2) && RoloSearch[2]) ||
		     (rr->text && re_exec(rr->text) && RoloSearch[3]) );
      re_free();
    } else
#endif
      for ( rr = RoloList; rr != NULL; rr = rr->next )
        rr->on = ( (rr->name && 
		    mystrstrcase(rr->name,s) != NULL &&
		    RoloSearch[0]) ||
		   (rr->number && 
		    mystrstrcase(rr->number,s) != NULL &&
		    RoloSearch[1]) ||
		   (rr->number2 &&
		    mystrstrcase(rr->number2,s) != NULL &&
		    RoloSearch[2]) ||
		   (rr->text && 
		    mystrstrcase(rr->text,s) != NULL &&
		    RoloSearch[3]) );
  }
}
