/*
 *	$Source$
 *	$Author$
 *	$Header$
 */

#ifndef lint
static char *rcsid_book_c = "$Header$";
#endif lint

#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include "bible.h"

#define MAX_BOOKS_OPEN 10

BOOK	booktab[NUMBOOKS];
BOOK	*current_book;

BOOK	*open_books[MAX_BOOKS_OPEN];
long	open_book_time;

int	bible_debug = 0;	/* It has to be definied somewhere! */

/*
 * Initialize the book table, and set things up to begin.
 */
init_booktab()
{
	int	i;
	FILE	*f;
	char	*cp;
	char	*line;

	current_book = NULL;
	open_book_time = 0;
	strcpy(tmp, LIBDIR);
	f = fopen(strcat(tmp, BOOKFILE), "r");
	if (!f) {
		perror(tmp);
		fprintf(stderr, "Can't open book table.... aborting...\n");
		exit(1);
	}
	for (i=0; i < NUMBOOKS; i++) {
		booktab[i].current_pos = -1; 	/* Undefined */
		booktab[i].last_used = -1; 	/* Not used */
		booktab[i].open_idx = -1;
		cp = fgets(tmp, sizeof(tmp), f);
		tmp[sizeof(tmp)-1] = '\0';
		line = strdup(tmp);
		booktab[i].f = NULL;
		if (!(cp = strtok(tmp, ":\n")))
			goto error;
		booktab[i].num = atoi(cp);
		if (!(cp = strtok(NULL, ":\n")))
			goto error;
		booktab[i].key = strdup(cp);
		if (!(cp = strtok(NULL, ":\n")))
			goto error;
		booktab[i].filename = strdup(cp);
		if (!(cp = strtok(NULL, ":\n")))
			goto error;
		booktab[i].numchap = atoi(cp);
		if (!(cp = strtok(NULL, ":\n")))
			goto error;
		booktab[i].abbrev = strdup(cp);
		if (!(cp = strtok(NULL, ":\n")))
			goto error;
		booktab[i].name = strdup(cp);
		if (cp = strtok(NULL, "")) {
			fprintf(stderr, "Extra fields, ignored: \n'%s'\n",
				cp);
		}
		free(line);
		continue;
	error:
		fprintf(stderr, "Parse error in the bible data file:\n");
		fprintf(stderr, "%s\n", line);
		free(line);
	}
	fclose(f);
	for (i = 0; i < MAX_BOOKS_OPEN; i++)
		open_books[i] = NULL;
}

close_book(b)
	BOOK	*b;
{
	if (!b || b->open_idx < 0)
		return;		/* Nothing to close out */
	if (b != open_books[b->open_idx])
		errout("Assertion failure in close_book");
	if (bible_debug)
		printf("Closing: %s\n", b->name);
	open_books[b->open_idx] = NULL;
	fclose(b->f);
	b->current_pos = -1;
	b->open_idx = -1;
	b->f = NULL;
}

open_book(b)
	BOOK	*b;
{
	int	i;
	int	new_slot;	/* Slot to free up */
	long	last_time;	/* Time last used by above */
	
	if (b->open_idx >= 0) {
		/*
		 * The book is already open, just update the counters
		 */
		b->last_used = open_book_time++;
		b = current_book;
		return(SUCCESS);
	}
	/*
	 * The book isn't open, yet.  Let's open the file descriptors
	 * and set things up.
	 */
	strcpy(tmp, LIBDIR);
	if (!(b->f = fopen(strcat(tmp, b->filename), "r"))) {
		perror(tmp);
		errout("Cannot open book text file!");
	}
	b->current_pos = 0;
	b->last_used = open_book_time++;
	current_book = b;
	
	/*
	 * OK, try to find a new slot for this book
	 */
	new_slot = 0;
	last_time = open_book_time;
	for (i=0; i < MAX_BOOKS_OPEN; i++) {
		if (!open_books[i]) {
			/*
			 * Here's an unused slot; use this one!
			 */
			open_books[i] = b;
			b->open_idx = i;
			return(SUCCESS);
		} else if (open_books[i]->last_used  < last_time) {
			new_slot = i;
			last_time = open_books[i]->last_used;
		}
	}
	/*
	 * OK, new_slot now contains the slot we should use
	 * for the newly open book.
	 */
	close_book(open_books[new_slot]);
	open_books[new_slot] = b;
	b->open_idx = new_slot;
	return(SUCCESS);
}

