#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include "rkive.h"
#include "maxart.h"

#ifdef STRDUP
char *strdup();
#endif

extern char maxartname[];
static char namebuf[MAXNAMLEN];

struct maxart {
     char *name;
     unsigned long int max;
};

static struct maxart *groups = 0;
static int ngroups = 0;
static int array_size = 0;

void open_maxart()
{
     FILE *in;
     long max;
     int found = 0;

     if (ngroups)
	  return;

     if (! array_size) {
	  groups = (struct maxart *) malloc(sizeof(struct maxart));
	  if (! groups) {
	       return;
	  }
	  array_size = 1;
     }

     if (! *maxartname) {
	  /* if maxartname isn't set, don't read from a file */
	  return;
     }
 
     in = fopen(maxartname, "r");
     
     if (! in) {
	  return;
     }

     while (fscanf(in, "%ld %s", &max, namebuf) == 2) {
	  found++;
	  set_maxart(namebuf, max);
     }

     fclose(in);

     if (found) {
	  FILE *out;
	  char buf[BUFSIZ];
	  char oldartname[MAXPATHLEN];

	  sprintf(oldartname, "%s.old", maxartname);
	  in = fopen(maxartname, "r");
	  out = fopen(oldartname, "w");
	  if (in && out) {
	       while (fgets(buf, sizeof(buf), in)) {
		    fputs(buf, out);
	       }
	  }
	  if (in)
	       fclose(in);
	  if (out)
	       fclose(out);
     }

     return;
}

static int find_group(group)
char *group;
{
     int min, max;

     /*
      * Do a binary search for the specified group in the array
      */

     min = 0;
     max = ngroups;

     while (min < max) {
	  int new = (min + max) / 2;
	  int srt = strcmp(group, groups[new].name);
	  if (! srt) {
	       /* found it! */
	       return(new);
	  }
	  else if (srt > 0) {
	       if (min == new) {
		    min++;
	       }
	       else {
		    min = new;
	       }
	       continue;
	  }
	  else {
	       max = new;
	       continue;
	  }
     }

     /* couldn't find it */
     return(ngroups);
}

unsigned long int get_maxart(group)
char *group;
{
     int where = find_group(group);

     if (where == ngroups) {
	  return(0);
     }
     else {
	  return(groups[where].max);
     }
}

static int compare_groups(p1, p2)
char *p1, *p2;
{
     struct maxart *q1 = (struct maxart *) p1;
     struct maxart *q2 = (struct maxart *) p2;

     return(strcmp(q1->name, q2->name));
}

void set_maxart(group, max)
char *group;
unsigned long int max;
{
     int where = find_group(group);
     if (where != ngroups) {
	  groups[where].max = max;
	  return;
     }

     /*
      * Add the new group to the array and sort it
      */

     if (! groups) {
	  return;
     }
     
     if (ngroups == array_size) {
	  array_size *= 2;
	  groups = (struct maxart *)
	       realloc(groups, sizeof(struct maxart) * array_size);
	  if (! groups) {
	       return;
	  }
     }
     
     groups[ngroups].name = strdup(group);
     groups[ngroups].max = max;
     ngroups++;

     if (ngroups > 1 &&
	 compare_groups((char *) &groups[ngroups-2],
			(char *) &groups[ngroups-1]) < 0) {
	  return;
     }
     else {
	  qsort((char *) groups, ngroups, sizeof(groups[0]), compare_groups);
     }

     return;
}

void save_maxart()
{
     FILE *out;
     int i;

     if (! *maxartname) {
	  return;
     }

     out = fopen(maxartname, "w");
     if (! out)
	  return;

     for (i = 0; i < ngroups; i++) {
	  fprintf(out, "%d %s\n", groups[i].max, groups[i].name);
     }

     fclose(out);
}
