/* 
	  subgetaa.c
 -- use sequence library composed of file of subset indices to full databank 
 -- d.g.gilbert, sep'95
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define XTERNAL
#include "altlib.h"
#include "uascii.gbl"
#include "upam.gbl"
#undef XTERNAL


#ifdef SUBSETLIB

/* ?? allow user-defined suffixes ?? */
#define  IndexSuffix ".indices"
#define  NamesSuffix ".names"

#define MAXLINE 512
static char datline[MAXLINE];
static unsigned char *savecp;

static short  curlibid = -1;
static short  curIsSeeked= 0;
static short  curseqform = -1;
static long   curdocstart = -1;
static long   curdatastart= -1;
static long   curdataend = -1;
static long 	curindexpos = -1;
static char   indexline[MAXLINE];
static char		curlibname[MAXLINE];
static FILEtype fIndex = NULL;
static FILEtype fNames = NULL;
static FILEtype fCurlib = NULL;


static short subset_opencurlib(short fileid)
{
	if (fCurlib == NULL) curlibid= -1;
	if (curlibid != fileid ) {
		fseek( fNames, 0, 0);
		while (curlibid != fileid) {
			long  seqformat, itsfileid;
			char  *cp;
			
			*indexline= 0;
			if (!fgets( indexline, MAXLINE, fNames)) return 0;
			/* fprintf( fofn,"%s\t%d\t%d\t%s\n", filename, seqformat, fileid, libname); */

			cp= indexline;
			while (*cp && !isspace(*cp)) cp++;
			if (*cp) *cp++= '\0';
			*curlibname= 0;
			itsfileid= -2;
			sscanf( cp, "%ld %ld %s", &seqformat, &itsfileid, curlibname);
			
			if (cp= strchr(curlibname,'\n')) *cp= 0;
			strcat(curlibname,":");
			
			if (itsfileid == fileid) {
				curlibid= fileid;
				curseqform= seqformat;
				if (fCurlib) fclose(fCurlib);
				fCurlib= fopen( indexline, "r");
				}
			}
		}
	return (fCurlib != NULL);
}


#define subset_seekcurentry( datastart)  { if (fCurlib) fseek( fCurlib, datastart, 0); }


static short agetname(char* libstr)
{
	*datline= 0;
	do {
		if (fgets( datline,MAXLINE,fCurlib)==NULL) return 0;
	} while (datline[0]!='>' && datline[0]!=';'); 
	strncpy(libstr,datline+1,20);
	libstr[10]='\0';
}

static short lgetname(char* libstr)
{
	*datline= 0;
	do {
		if (fgets(datline,MAXLINE,fCurlib)==NULL) return 0;
	} while (datline[0]!='L' || datline[1] !='O' || strncmp(datline,"LOCUS",5)); 
	strncpy(libstr,&datline[11],10);
	libstr[10]='\0';
}

static short pgetname(char* libstr)
{
	*datline= 0;
	do {
		if (fgets(datline,MAXLINE,fCurlib)==NULL) return 0;
	} while (datline[0]!='E' || datline[1]!='N' || strncmp(datline,"ENTRY",5)); 
	strncpy(libstr,&datline[17],8); /* 17 was 16 */
	libstr[8]='\0';
}

static short egetname(char* libstr)
{
	char *id;
	*datline= 0;
	do {
		if (fgets(datline,MAXLINE,fCurlib)==NULL) return 0;	
	} while (datline[0]!='I' || datline[1]!='D');
	strncpy(libstr,&datline[5],10);
	libstr[10]='\0';
	/* sscanf(&datline[5],"%s",id); sprintf(libstr,"%-10.10s",id); ?? bad */
}

static short igetname(char* libstr)
{
	char *bp;
	*datline= 0;
	do {
		if (fgets(datline,MAXLINE,fCurlib)==NULL) return 0;	
	} while (datline[0]!=';');
	while (datline[0]==';') fgets(datline,sizeof(datline),fCurlib);
	strncpy(libstr,datline+1,10);
	libstr[9]='\0';
	if ( (bp = strchr(libstr,'\n')) ) *bp='\0';
}

static short vgetname(char* libstr)
{
	char *bp;
	*datline= 0;
	do {
		if (fgets(datline,MAXLINE,fCurlib)==NULL) return 0;	
	} while (datline[0]!='>' && datline[0]!=';');
	if ( (bp = strchr(datline,'\n')) ) *bp='\0';
	strncpy(libstr,&datline[4],20);
	libstr[10]='\0';
}



static void subset_getname( char* name)
{
	/* long atnow atnow= ftell(fCurlib); */
	strcpy(name,curlibname);
	name += strlen(name);
	subset_seekcurentry( curdocstart);
	switch (curseqform) {
		case DEFAULT 	:  agetname( name); break;
		case FULLGB 	:  lgetname( name); break; 
		case UNIXPIR 	:  pgetname( name); break; 
		case EMBLSWISS:  egetname( name); break; 
		case INTELLIG :  igetname( name); break; 
		case VMSPIR 	:  vgetname( name); break; 
		}
	/* fseek( fCurlib, atnow, 0); */
}

static void subset_gettitle(char* name, long maxname)
{
	FILEtype oldlib;
	/* long atnow = ftell(fCurlib); */
	long  len1;
	strcpy(name,curlibname);
	len1 = strlen(name);
	name += len1;
	maxname -= len1;
	
	subset_seekcurentry( curdocstart);
	oldlib= setlib(fCurlib);
	switch (curseqform) {
		case DEFAULT 	:  aranlib( name, maxname, curdocstart); break;
		case FULLGB 	:  lranlib( name, maxname, curdocstart); break; 
		case UNIXPIR 	:  
			{
			/*dgg- fix off-by-1 bug in nxgetaa's pranlib get of ENTRY name... */
			char name1[256];
			pranlib( name1, maxname, curdocstart); 
			strcat(name, name1 + 1);
			}
			break; 
			

		case EMBLSWISS: eranlib( name, maxname, curdocstart);  break; 
		case INTELLIG :  iranlib( name, maxname, curdocstart); break; 
		case VMSPIR 	:  vranlib( name, maxname, curdocstart); break; 
		}
	setlib(oldlib);
	/* fseek( fCurlib, atnow, 0); */
}


static short subset_locatenextentry()
{
	long  fileid, docstart, datastart, dataend;
	char *lp;
		/* 1. find next entry in library file */
	fileid= -1;
	*indexline= 0;
	curindexpos = ftell(fIndex);
	lp= fgets( indexline, MAXLINE, fIndex); /* ?? buggy return value to fgets() ? */
	if ( lp==NULL || *lp == 0) return -1;
	
	sscanf( indexline, "%ld %ld %ld %ld", &fileid, &docstart, &datastart, &dataend);
	curdocstart= docstart;
	curdatastart= datastart;
	curdataend= dataend;
	return fileid;
}

static short subset_seekindex( long indexpos)
{
	short isokay, fileid;
	fseek( fIndex, indexpos, 0);
	fileid= subset_locatenextentry();	
	isokay= subset_opencurlib(fileid);
	curIsSeeked= 1;
	return isokay;
}



short subset_openlib(char* libname)
{
	short fileid, isokay = 1;
	char  name[512];
	/* libname format is like '/somewhere/temp/sublibs  12' , last num is libtype */
	
	strncpy( name, libname, sizeof(name));
	strncat( name, IndexSuffix, sizeof(name));
	fIndex= fopen( name, "r");
	if (!fIndex) return 0;
	
	strncpy( name, libname, sizeof(name));
	strncat( name, NamesSuffix, sizeof(name));
	fNames= fopen( name, "r");
	if (!fNames) return 0;

#if 0	
		/* do this in _getlib */
	fileid= subset_locatenextentry();	
	fseek( fIndex, 0, 0); /* reset to 1st entry for _getlib */
	isokay= subset_opencurlib(fileid);
#endif
	return isokay;
}

void subset_closelib()
{
	if (fIndex) fclose(fIndex); fIndex= NULL;
	if (fNames) fclose(fNames); fNames= NULL;
	if (fCurlib) fclose(fCurlib); fCurlib= NULL;
}



subset_getlib(seq,maxs,libstr,libpos,lcont)
	unsigned char *seq;
	int maxs;
	char *libstr;
	long *libpos;
	int *lcont;
{
	int i, n, ll;
	int ic;
	register unsigned char *cp, *seqp;
	register int *ap;
  unsigned char *seqm, *seqm1;
	char *linep;

	short  seqformat, fileid, isokay;
	char	* filename;

	seqp = seq;
	seqm = &seq[maxs-11];
	seqm1 = seqm-1;
#ifndef TFASTA
	ap = sascii;
#else
	ap = nascii;
#endif

	if (*lcont==0) {
			/* 1. find next entry in library file */
			/* ! but not if last call was to RANLIB w/ seek to this record ! */
		if (curIsSeeked)  {
			curIsSeeked= 0;
			isokay= 1;
			}
		else {
			fileid= subset_locatenextentry();	
			isokay= subset_opencurlib(fileid);
			if (!isokay) return 0;
			}
		
			/* 2. save entry name & entry file offset  */
	  *libpos= curindexpos; /* used by RANLIB to seek current record */
		subset_getname( libstr);
					
			/* 3. locate data start in entry  */
		subset_seekcurentry( curdatastart);
		}
		
	else {
		for (cp= savecp; seqp<seqm1; ) {
			if ((*seqp++=ap[*cp++])<NA) continue;
			if (*(--seqp)>NA) break;
			}
		}

	datline[0]='\0';
	while (seqp<seqm1 
	      && fgets(datline,sizeof(datline),fCurlib)!=NULL) 
	  {
	  	/* end of data, return */
		if (ftell(fCurlib) >= curdataend) goto new; 
		
			/* read data, store in seqp */
		for (cp= (unsigned char*) &datline[10]; seqp<seqm1; ) {
			if ((*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA &&
					(*seqp++=ap[*cp++])<NA) continue;
					if (*(--seqp)>NA) break;
					}
		}
	goto done;
	
new:	
		;
		
done:	
  if (seqp>=seqm1) {
		savecp = cp;
		(*lcont)++;
		}
	else *lcont=0;

	*seqp = EOSEQ;
	if ((int)(seqp-seq)==0) return 1;
	return (int)(seqp-seq);
}


subset_ranlib(str,cnt,seek)
	char *str; int cnt; long seek;
{
	if ( subset_seekindex( seek) ) {
		subset_gettitle( str, cnt);
		subset_seekcurentry( curdatastart);
		}
}


#endif /*SUBSETLIB*/
