/*
 * notify.c: a few handy routines to notify you when people enter and leave irc 
 *
 * Written By Michael Sandrof
 * Copyright(c) 1990 
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Revamped by lynX - Dec '91
 */
#include <stdio.h>
#include "irc.h"
#include "list.h"
#include "notify.h"
#include "ircaux.h"
#include "whois.h"
#include "hook.h"
#include "server.h"
#include "output.h"

/* NotifyList: the structure for the notify stuff */
typedef	struct	notify_stru
{
	struct	notify_stru	*next;	/* pointer to next notify person */
	char	*nick;			/* nickname of person to notify about */
	int	flag;			/* 1=person on irc, 0=person not on irc */
}	NotifyList;

static	NotifyList	*notify_list = null(NotifyList *);

extern void	ison_notify();

/* Rewritten, -lynx */
void	show_notify_list(all)
int	all;
{
	NotifyList	*tmp;
	char	*list = null(char *);

	malloc_strcpy(&list, empty_string);
	for (tmp = notify_list; tmp; tmp = tmp->next)
	{
		if (tmp->flag)
		{
			malloc_strcat(&list, " ");
			malloc_strcat(&list, tmp->nick);
		}
	}
	if (*list)
		say("Currently present:%s", list);
	if (all)
	{
		malloc_strcpy(&list, empty_string);
		for (tmp = notify_list; tmp; tmp = tmp->next)
		{
			if (!(tmp->flag))
			{
				malloc_strcat(&list, " ");
				malloc_strcat(&list, tmp->nick);
			}
		}
		if (*list) say("Currently absent:%s", list);
	}
	new_free(&list);
}

/* notify: the NOTIFY command.  Does the whole ball-o-wax */
/*ARGSUSED*/
void	notify(command, args)
char	*command,
	*args;
{
	char	*nick,
		*list = null(char *),
		*ptr;
	int	no_nicks = 1;
	int	do_ison = 0;
	NotifyList	*new;

	malloc_strcpy(&list, empty_string);
	while (nick = next_arg(args, &args))
	{
		no_nicks = 0;
		while (nick)
		{
			if (ptr = index(nick, ','))
				*(ptr++) = null(char);
			if (*nick == '-')
			{
				nick++;
				if (*nick)
				{
					if (new = (NotifyList *)
						remove_from_list(&notify_list,
						nick))
					{
						new_free(&(new->nick));
						new_free(&new);
						say("%s removed from \
notification list", nick);
					}
					else
						say("%s is not on the \
notification list", nick);
				}
				else
					show_notify_list(0);
			}
			else
			{
				/* compatibility */
				if (*nick == '+')
					nick++;
				if (*nick)
				{
					do_ison = 1;
					if (index(nick, '*'))
						say("Wildcards not allowed in \
NOTIFY nicknames!");
					else
					{
						if (new = (NotifyList *)
					remove_from_list(&notify_list, nick))
						{
							new_free(&(new->nick));
							new_free(&new);
						}
						new = (NotifyList *)
						 new_malloc(sizeof(NotifyList));
						new->nick = null(char *);
						malloc_strcpy(&(new->nick),
							nick);
						new->flag = 0;
						add_to_list(&notify_list, new);
						from_server = primary_server;
						if (get_server_2_6_2(
								from_server))
						{
							malloc_strcat(&list,
								new->nick);
							malloc_strcat(&list,
								" ");
						}
						else
							add_to_whois_queue(
								new->nick,
								whois_notify,
								null(char *));
						say("%s added to the \
notification list", nick);
					}
				} else
					show_notify_list(0);
			}
			nick = ptr;
		}
	}
	if (do_ison)
		add_ison_to_whois(list, ison_notify);
	new_free(&list);
	if (no_nicks)
		show_notify_list(1);
}

/*
 * do_notify: This simply goes through the notify list, sending out a WHOIS
 * for each person on it.  This uses the fancy whois stuff in whois.c to
 * figure things out.  Look there for more details, if you can figure it out.
 * I wrote it and I can't figure it out.
 *
 * Thank you Michael... leaving me bugs to fix :) Well I fixed them!
 */
void	do_notify()
{
	static	int	location = 0;
	int	count,
		c2;
	char	buf[BIG_BUFFER_SIZE+1];
	NotifyList	*tmp;

	*buf = '\0';
	from_server = primary_server;
	for (tmp = notify_list, c2 = count = 0; tmp; tmp = tmp->next, count++)
	{
		if (count >= location && count < location + 40)
			if (get_server_2_6_2(from_server))
			{
				c2++;
				strcat(buf, " ");
				strcat(buf, tmp->nick);
			}
			else
				add_to_whois_queue(tmp->nick, whois_notify,
						null(char *));
	}
	if (get_server_2_6_2(from_server) && c2)
		add_ison_to_whois(buf, ison_notify);
	if ((location += 40) > count)
		location = 0;
}

/*
 * notify_mark: This marks a given person on the notify list as either on irc
 * (if flag is 1), or not on irc (if flag is 0).  If the person's status has
 * changed since the last check, a message is displayed to that effect.  If
 * the person is not on the notify list, this call is ignored 
 */
void	notify_mark(nick, flag)
char	*nick;
int	flag;
{
	NotifyList	*tmp;

	if (tmp = (NotifyList *) list_lookup(&notify_list, nick,
			!USE_WILDCARDS, !REMOVE_FROM_LIST))
	{
		if (flag)
		{
			if (tmp->flag != 1)
			{
				if (tmp->flag != -1 &&
				    do_hook(NOTIFY_SIGNON_LIST, "%s", nick))
					say("Signon by %s detected", nick);
				/*
				 * copy the correct case of the nick
				 * into our array  ;)
				 */
				malloc_strcpy(&(tmp->nick), nick);
				malloc_strcpy(&last_notify_nick, nick);
				tmp->flag = 1;
			}
		}
		else
		{
			if (tmp->flag == 1 && do_hook(NOTIFY_SIGNOFF_LIST,
					"%s", nick))
				say("Signoff by %s detected", nick);
			tmp->flag = 0;
		}
	}
}

void	save_notify(fp)
FILE	*fp;
{
	NotifyList	*tmp;

	if (notify_list)
	{
		fprintf(fp, "NOTIFY");
		for (tmp = notify_list; tmp; tmp = tmp->next)
			fprintf(fp, " %s", tmp->nick);
		fprintf(fp, "\n");
	}
}
