/**************************************************************************
*                                                                         *
*                             COPYRIGHT NOTICE                            *
*                                                                         *
* This software/database is categorized as "United States Government      *
* Work" under the terms of the United States Copyright Act.  It was       *
* produced as part of the author's official duties as a Government        *
* employee and thus can not be copyrighted.  This software/database is    *
* freely available to the public for use without a copyright notice.      *
* Restrictions can not be placed on its present or future use.            *
*                                                                         *
* Although all reasonable efforts have been taken to ensure the accuracy  *
* and reliability of the software and data, the National Library of       *
* Medicine (NLM) and the U.S. Government do not and can not warrant the   *
* performance or results that may be obtained by using this software,     *
* data, or derivative works thereof.  The NLM and the U.S. Government     *
* disclaim any and all warranties, expressed or implied, as to the        *
* performance, merchantability or fitness for any particular purpose or   *
* use.                                                                    *
*                                                                         *
* In any work or product derived from this material, proper attribution   *
* of the author(s) as the source of the software or data would be         *
* appreciated.                                                            *
*                                                                         *
**************************************************************************/
#include <ncbi.h>
#include "blastapp.h"

#define SEQLINE_LEN	60

/* hsp_print - print HSP when query & subject are both a.a. sequences */
int
hsp_print(fp, hp, flagscore, q, s, mat, q_btoa, s_btoa, q_len, s_len, fqpos0, fqpos1, fspos0, fspos1, framelabel, str_frame, lambda)
	FILE	*fp;
	HSPPtr	hp;
	CharPtr		flagscore;
	register UcharPtr	q, s;
	Score_t	mat[ALPHAVAL_MAX+1][ALPHAVAL_MAX+1];
	CharPtr	q_btoa, s_btoa; /* binary to ascii lookup tables */
	unsigned long	q_len, s_len; /* total length of query and subject */
	long	(*fqpos0)(), (*fqpos1)();
	long	(*fspos0)(), (*fspos1)();
	CharPtr	framelabel;
	CharPtr	(*str_frame)PROTO((int));
	double	lambda;
{
	UcharPtr	q0 = q, s0 = s;
	unsigned long	spos = hp->s_pos, qpos = hp->q_pos;
	char	outbuf[SEQLINE_LEN];
	register CharPtr	bp, bpmax;
	register UcharPtr	cp;
	UcharPtr	qmax;
	int		mlen, width;
	unsigned long	nbr_ident, nbr_pos;
	long	qcoord, scoord;
	size_t	j;
	register unsigned char	cs, cq;

	nbr_ident = nbr_pos = 0;
	for (qmax = q + hp->len; q < qmax; )
		if (mat[cq = *q++][cs = *s++] > 0) {
			++nbr_pos;
			if (q_btoa[cq] == s_btoa[cs])
				++nbr_ident;
		}

	(void) fprintf(fp, "\n Score = %ld%s (%.1lf bits), Expect = %#0.2lg, ",
			(long)hp->score, flagscore, ((double)hp->score)*(lambda/LN2),
			hp->expect);

	if (hp->n < 2)
		(void) fprintf(fp, "P = %#0.2lg\n", hp->P_val);
	else
		(void) fprintf(fp, "Poisson P(%u) = %#0.2lg\n", hp->n, hp->P_val);

	(void) fprintf(fp,
			" Identities = %lu/%u (%u%%), Positives = %lu/%u (%u%%)",
			nbr_ident, hp->len, (unsigned)((100*nbr_ident)/hp->len),
			nbr_pos, hp->len, (unsigned)((100*nbr_pos)/hp->len) );

	if (framelabel != NULL) {
		fputs(", ", fp);
		fputs(framelabel, fp);
		fputs(" = ", fp);
		fputs((*str_frame)(hp->frame), fp);
	}
	putc('\n', fp);

	for (q = q0, s = s0; q < qmax; ) {
		mlen = MIN(qmax - q, SEQLINE_LEN);
		qcoord = (*fqpos0)(q_len, hp->frame, qpos, Qoffset);
		scoord = (*fspos0)(s_len, hp->frame, spos, 0);
		width = MAX(5, longwidth10(qcoord));
		width = MAX(width, longwidth10(scoord));

		bp = outbuf, bpmax = bp + mlen;
		cp = q;
		do {
			*bp++ = q_btoa[*cp++];
		} while (bp < bpmax);

		(void) fprintf(fp, "\nQuery: %*ld ", width, qcoord);
			(void) fwrite(outbuf, mlen, 1, fp);
			qcoord = (*fqpos1)(q_len, hp->frame, qpos + mlen - 1, Qoffset);
			(void) fprintf(fp, " %ld\n", qcoord);

		(*printmid)(fp, q, s, mlen, mat, q_btoa, s_btoa, width);

		bp = outbuf, bpmax = bp + mlen;
		cp = s;
		do {
			*bp++ = s_btoa[*cp++];
		} while (bp < bpmax);

		(void) fprintf(fp, "Sbjct: %*ld ", width, scoord);
			(void) fwrite(outbuf, mlen, 1, fp);
			scoord = (*fspos1)(s_len, hp->frame, spos + mlen - 1, 0);
			(void) fprintf(fp, " %ld\n", scoord);

		q += mlen;
		s += mlen;
		qpos += mlen;
		spos += mlen;
	}
	return ferror(fp);
}

void
printmid0(fp, s1, s2, len, mat, q_btoa, s_btoa, width)
	FILE	*fp;
	register UcharPtr	s1, s2;
	int		len;
	Score_t	mat[ALPHAVAL_MAX+1][ALPHAVAL_MAX+1];
	register CharPtr	q_btoa, s_btoa;
	int		width;
{
	register CharPtr	bp, bpmax;
	register unsigned char	c1, c2;
	register char	a1;
	int		i;
	char	buf[SEQLINE_LEN];

	for (i = 0; i < width+8; ++i)
		putc(' ', fp);
	for (bp = buf, bpmax = bp + len; bp < bpmax; ++bp) {
		if (mat[c1 = *s1++][c2 = *s2++] > 0)
			if ((a1 = q_btoa[c1]) == s_btoa[c2])
				*bp = a1;
			else
				*bp = '+';
		else
			*bp = ' ';
	}
	fwrite(buf, len, 1, fp);
	putc('\n', fp);
}

void
printmid1(fp, s1, s2, len, mat, q_btoa, s_btoa, width)
	FILE	*fp;
	register UcharPtr	s1, s2;
	int		len;
	Score_t	mat[ALPHAVAL_MAX+1][ALPHAVAL_MAX+1];
	register CharPtr	q_btoa, s_btoa;
	int		width;
{
	register CharPtr	bp, bpmax;
	int		i;
	char	buf[SEQLINE_LEN];

	for (i = 0; i < width+8; ++i)
		putc(' ', fp);
	for (bp = buf, bpmax = bp + len; bp < bpmax; ++bp) {
		if (mat[*s1++][*s2++] > 0)
			*bp = '|';
		else
			*bp = ' ';
	}
	fwrite(buf, len, 1, fp);
	putc('\n', fp);
}

CharPtr
str_frame(frame)
	register int		frame;
{
	static char	buf[20];

	switch (frame) {
	case 1: return "+1";
	case 2: return "+2";
	case 3: return "+3";
	case 0: return "Undefined";
	case -1: return "-1";
	case -2: return "-2";
	case -3: return "-3";
	default:
		sprintf(buf, "%+d", frame);
		return buf;
	}
}

CharPtr
str_strand(strand)
	int		strand;
{
	if (strand > 0)
		return "Plus";
	if (strand < 0)
		return "Minus";
	return "Undefined";
}
