#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/subs/wu.c,v 2.8 1995/10/01 22:14:42 empire Exp $";
#endif

/*
 * wu.c
 *
 * write a telegram to a user from another.
 *
 * from PSL Empire, 1985
 */

#include <varargs.h>
#include "misc.h"
#include <fcntl.h>
#include <sys/uio.h>
#include "nat.h"
#include "tel.h"
#include "file.h"
#include "player.h"
#include "edb.h"

/*
 * telegram_is_new counts new telegrams the same as read_telegrams in 
 * lib/commands/mail.c and lib/commands/rea.c
 */

static int
telegram_is_new (to, tel)
	natid to;
	struct telstr *tel;

{
	extern	int	update_pending;
	static	struct	telstr last_tel[MAXNOC];
	int is_new = 0;

	is_new |= tel->tel_type != last_tel[to].tel_type;
	is_new |= tel->tel_from != last_tel[to].tel_from;
	is_new |= !update_pending && /* sometimes updates take a long time */
		  abs (tel->tel_date - last_tel[to].tel_date) > TEL_SECONDS;
	
	last_tel[to].tel_type = tel->tel_type;
	last_tel[to].tel_from = tel->tel_from;
	last_tel[to].tel_date = tel->tel_date;

	return is_new;
}

/*VARARGS*/
wu(va_alist)
	va_dcl
{
	natid	from;
	natid	to;
	struct natstr *np;
	s_char	*format;
	va_list	ap;
	s_char	buf[4096];
	struct player *other;
	extern	int	update_pending;

	va_start(ap);
	from = va_arg(ap, int);
	to = va_arg(ap, int);
	format = va_arg(ap, s_char *);
	(void) vsprintf(buf, format, ap);
	va_end(ap);
	np = getnatp(from);
	if (update_pending)
		return typed_wu(from, to, buf, TEL_UPDATE);
	else if (np->nat_stat & STAT_GOD)
		return typed_wu(from, to, buf, TEL_BULLETIN);
	else
		return typed_wu(from, to, buf, TEL_NORM);
}

int
typed_wu(from, to, message, type)
	natid	from;
	natid	to;
	s_char	*message;
	int	type;
{
	register s_char *bp;
	int	len;
	struct	telstr tel;
	struct	natstr *np;
	struct	iovec iov[2];
	int	fd;
	s_char	box[1024];
	int	notify = 0;
	int     new_tele = 0;
	struct player *other;

	if (type == TEL_ANNOUNCE)
		strcpy(box, annfil);
	else
		mailbox(box, to);

	if (type != TEL_ANNOUNCE)
		if ((np = getnatp(to)) == 0 ||
		    ((np->nat_stat & STAT_NORM) == 0 &&
		     (np->nat_stat & STAT_SANCT) == 0)) {
			return -1;
		}

	if ((fd = open(box, O_WRONLY|O_APPEND, 0)) < 0) {
		logerror("telegram 'open' of %s (#%d) failed", box, to);
		return -1;
	}
	tel.tel_from = from;
	(void) time(&tel.tel_date);
	bp = message;
	while (*bp++)
		;
	len = bp - message;
	if (len >= MAXTELSIZE)
		len = MAXTELSIZE;
	message[len] = 0;
	tel.tel_length = len;
	tel.tel_type = type;
	iov[0].iov_base = (caddr_t) &tel;
	iov[0].iov_len = sizeof(tel);
	iov[1].iov_base = message;
	iov[1].iov_len = len;
	if (writev(fd, iov, 2) < iov[0].iov_len + iov[1].iov_len) {
		logerror("telegram 'write' to #%d failed", to);
	} else if (type == TEL_ANNOUNCE) {
		for (to=0; np = getnatp(to); to++) {
			if (!(np->nat_stat & STAT_NORM) &&
			    !(np->nat_stat & STAT_SANCT))
				continue;
			if (!player->god && (getrejects(from,np) & REJ_ANNO))
				continue;
			notify = (np->nat_ann == 0);
			np->nat_ann++;
			putnat(np);
			prsync(np->nat_cnum, np, EDV_ALL);
			if (notify)
				player_wakeup_all(to);			
		}
	} else {
		notify = (np->nat_tgms == 0);
		new_tele = telegram_is_new(to, &tel);
		np->nat_tgms += new_tele || notify;
		putnat(np);
		prsync(np->nat_cnum, np, EDV_ALL);

		if (new_tele && np->nat_flags & NF_INFORM) {
			if (other = getplayer(to)) {
				if (np->nat_tgms == 1)
					pr_inform(other, "[new tele]\n");
				else
					pr_inform(other, "[%d new teles]\n",
						  np->nat_tgms);
				player_wakeup_all(to);
			}
		} else if (notify)
			player_wakeup_all(to);
	}

	close(fd);
	return 0;
}

