/*
Copyright (C) 1997 by Warren R. Gish.  All Rights Reserved.
*/
#include <ncbi.h>
#include "nrdb.h"

#define SEQLINE_LEN	60

extern NRFilePtr	*files;

static void	uncompress2bits PROTO((SeqStrPtr, UcharPtr));
static void	uncompress4bits PROTO((SeqStrPtr, UcharPtr));

Report(list)
	SeqStrPtr	list;
{
	register char	*cp;
	register long	i;
	char	*seqp;

	for (; list != NULL; list = list->chain) {
		prt_header(list);
		cp = seqp = list->seq;
		if (list->clen != 0) {
			if (list->compression == 4)
				uncompress4bits(list, seqbuf);
			else
				uncompress2bits(list, seqbuf);
			cp = seqp = (CharPtr)seqbuf;
		}
		while ((i = list->seqlen - (cp - seqp)) > 0) {
			i = MIN(i, SEQLINE_LEN);
			if (fwrite(cp, i, 1, ofp) != 1)
				fatal(1, "Report:  fwrite error:  %s", strerror(errno));
			if (putc_unlocked('\n', ofp) != '\n')
				fatal(1, "Report:  putc error:  %s", strerror(errno));
			cp += i;
		}
		if (ferror(ofp))
			fatal(1, "nrdb:  error on output file:  %s", strerror(errno));
	}
	return 0;
}


int
prt_header(list)
	SeqStrPtr	list;
{
	register SeqNamePtr	snp;
	register long	totnamelen = 0;
	int		desc_cnt = 0;

	for (snp = list->name1; snp != NULL; snp = snp->chain) {
		if (desc_max > 0 && desc_cnt >= desc_max)
			break;
		if (++desc_cnt == 1) {
			if (putc_unlocked('>', ofp) != '>')
				fatal(1, "Report:  putc error:  %s", strerror(errno));
		}
		else {
			if (putc_unlocked(delim, ofp) != delim)
				fatal(1, "Report:  putc error:  %s", strerror(errno));
		}
		if (snp->nrfp->dbnamelen > 0) {
			if (fwrite(snp->nrfp->dbname, snp->nrfp->dbnamelen, 1, ofp) != 1)
				fatal(1, "Report:  fwrite error:  %s", strerror(errno));
			if (putc_unlocked(':', ofp) != ':')
				fatal(1, "Report:  putc error:  %s", strerror(errno));
		}
		if (fwrite(snp->name, snp->namelen, 1, ofp) != 1)
			fatal(1, "Report:  fwrite error:  %s", strerror(errno));
		totnamelen += (snp->namelen+1);
	}
	if (putc_unlocked('\n', ofp) != '\n')
		fatal(1, "Report:  putc error:  %s", strerror(errno));

	if (totnamelen > maxwnamelen)
		maxwnamelen = totnamelen;
	return 0;
}

static void
uncompress2bits(ssp, seqp)
	SeqStrPtr	ssp;
	register UcharPtr	seqp;
{
	register unsigned char	*cseqp;
	register unsigned char	ch;
	unsigned char	*cseqpend;
	int		cnt;

	cseqp = (unsigned char *) ssp->seq;

	for (cseqpend = cseqp + (ssp->seqlen / 4); cseqp < cseqpend; ++cseqp, seqp += 4) {
		ch = *cseqp;
		seqp[3] = nt_btoa[ch & 0x03];
		seqp[2] = nt_btoa[(ch >>= 2) & 0x03];
		seqp[1] = nt_btoa[(ch >>= 2) & 0x03];
		seqp[0] = nt_btoa[(ch >> 2)];
	}

	cnt = (ssp->seqlen % 4);
	if (cnt > 0) {
		ch = (*cseqp >> ((3-cnt) * 2));
		while (cnt--) {
			ch >>= 2;
			seqp[cnt] = nt_btoa[ch & 0x03];
		}
	}
	seqp[ssp->seqlen % 4] = NULLB;

	return;
}

static void
uncompress4bits(ssp, seqp)
	SeqStrPtr	ssp;
	register UcharPtr	seqp;
{
	register unsigned char	*cseqp;
	register unsigned char	ch;
	unsigned char	*cseqpend;
	int		cnt;

	cseqp = (unsigned char *) ssp->seq;

	for (cseqpend = cseqp + (ssp->seqlen / 2); cseqp < cseqpend; ++cseqp, seqp += 2) {
		ch = *cseqp;
		seqp[1] = nt_btoa[ch & 0x0f];
		seqp[0] = nt_btoa[(ch >> 4)];
	}

	cnt = (ssp->seqlen % 2);
	if (ssp->seqlen & 0x01)
		*seqp++ = nt_btoa[(*cseqp)>>4];
	*seqp = NULLB;

	return;
}

