/*
 * notice.c: special stuff for parsing NOTICEs
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1991
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 */

#if 0
static	char	rcsid[] = "@(#)$Id: notice.c,v 1.18 1994/07/02 02:32:13 mrg Exp $";
#endif

#include "irc.h"

#include "ctcp.h"
#include "window.h"
#include "lastlog.h"
#include "flood.h"
#include "vars.h"
#include "ircaux.h"
#include "hook.h"
#include "ignore.h"
#include "server.h"
#include "funny.h"
#include "output.h"
#include "names.h"
#include "parse.h"
#include "notify.h"
#include "commands.h"

static	time_t 	convert_note_time_to_real_time (char *stuff);
static	int 	kill_message (const char *from, char *line);
	int	doing_notice;


/*
 * The client apparantly never was adapted to handle the new NOTE syntax.
 * So i had to kludge this up to work with it.  Currently, NOTEs are sent
 * something like this:
 *
 *	NOTICE yournick :Note from nick!user@host /xxxd:xxh:xxm/ [N] message
 *
 * and parse() calls parse_notice(), who notices that there is no pefix
 * and passes it off to parse_server_notice(), who checks to see if it is
 * a note (it is), blows away the "Note from" part, and re-sets the "from"
 * and "FromUserHost" parts with the nick!user@host part and passes us the
 * buck with 'line' pointing at the time description (the /.../ part)
 */
static void parse_note (char *from, char *line)
{
	char	*date,
		*flags,
		*high;
	time_t	when;
	int 	level;

	switch (check_ignore(from, FromUserHost, IGNORE_NOTES))
	{
		case IGNORED:
			return;
		case HIGHLIGHTED:
			high = highlight_char;
			break;
		default:
			high = empty_string;
	}

	if (!check_flooding(from, NOTE_FLOOD, line))
		return;

/* 
	at this point, line looks like:
	"/xxxd:xxh:xxm/ [FLAGS] message goes here"
 */
	date = next_arg(line, &line);
	flags = next_arg(line, &line);

	when = convert_note_time_to_real_time(date);
	level = set_lastlog_msg_level(LOG_NOTES);

	if (do_hook(NOTE_LIST, "%s %lu %s", from, when, line))
	{
		if (time(NULL) - when > 60)	/* not just sent */
			put_it("%s[%s]%s %s (%s)", high, from, high, line, my_ctime(when));
		else
			put_it("%s[%s]%s %s", high, from, high, line);
	}

	if (beep_on_level & LOG_NOTES)
		beep_em(1);
	set_lastlog_msg_level(level);
}

static time_t convert_note_time_to_real_time(char *stuff)
{
	time_t days = 0, hours = 0, minutes = 0;

	stuff++;			      /* first character is a '/' */
	days = strtoul(stuff, &stuff, 10);    /* get the number of days */
	stuff++;			      /* skip over the 'd' */
	stuff++;			      /* skip over the ':' */
	hours = strtoul(stuff, &stuff, 10);   /* get the number of hours */
	stuff++;			      /* skip over the 'h' */
	stuff++;			      /* skip over the ':' */
	minutes = strtoul(stuff, &stuff, 10); /* get the number of minutes */
	stuff++;			      /* skip over the 'm' */
	stuff++;			      /* skip over the '/' */
	if (*stuff)
		yell("cntto: bad format");

	hours += days * 24;
	minutes += hours * 60;
	return (time(NULL) - minutes * 60);
}

static 	void 	parse_server_notice (char *from, char *line)
{
	int	lastlog_level;
	int	hooked = 0;
	const char *	f;

	f = from;
	if (!f || !*f)
		if (!(f = get_server_itsname(from_server)))
			f = get_server_name(from_server);

	/* OPERator Notices */
	if (!strncmp(line, "*** Notice -- ", 13))
	{
		if (!strncmp(line + 14, "Received KILL message for ", 26))
			hooked = kill_message(f, line + 40);

		if (!hooked)
		{
			message_from(NULL, LOG_OPNOTE);
			lastlog_level = set_lastlog_msg_level(LOG_OPNOTE);
			if (!do_hook(OPER_NOTICE_LIST, "%s %s", f, line + 14))
				hooked = 1;
		}
	}

	/* NOTEs */
	else if (!strncmp(line, "Note", 4))
	{
		char *note_from = NULL;
		if (strlen(line) > 10)
		{
			line += 10; /* skip the "Note from" part */
			note_from = line;
			if ((line = strchr(note_from, '!')))
			{
				*line++ = 0;
				FromUserHost = line;
				if ((line = strchr(FromUserHost, ' ')))
				{
					*line++ = 0;
					parse_note(note_from, line);
				}
			}
		}
		return;
	}

	message_from(NULL, LOG_SNOTE);
	lastlog_level = set_lastlog_msg_level(LOG_SNOTE);

	/* Check to see if the notice already has its own header... */
	if (*line == '*' || *line == '#')
	{
		if (!hooked && do_hook(SERVER_NOTICE_LIST, "%s %s", f, line))
			put_it("%s", line);
	}
	else
		if (!hooked && do_hook(SERVER_NOTICE_LIST, "%s *** %s", f, line))
			say("%s", line);

	if (lastlog_level)
	{
		set_lastlog_msg_level(lastlog_level);
		message_from(NULL, lastlog_level);
	}
}

void 	parse_notice (char *from, char **Args)
{
	int	level,
		type;
	char	*to;
	int	no_flooding;
	char	*high,
		not_from_server = 1;
	char	*line;

	PasteArgs(Args, 1);
	to = Args[0];
	line = Args[1];
	if (!to || !line)
		return;
	doing_notice = 1;

	if (*to)
	{
		if (is_channel(to))
		{
			message_from(to, LOG_NOTICE);
			type = PUBLIC_NOTICE_LIST;
		}
		else
		{
			message_from(from, LOG_NOTICE);
			type = NOTICE_LIST;
		}

		if (from && *from && strcmp(get_server_itsname(from_server), from))
		{
			switch (check_ignore_channel(from, FromUserHost, to, IGNORE_NOTICES))
			{
				case IGNORED:
					doing_notice = 0;
					return;
				case HIGHLIGHTED:
					high = highlight_char;
					break; /* oops! */
				default:
					high = empty_string;
			}

	/*
	 * only dots in servernames, right ?
	 *
	 * But a server name doesn't nessicarily have to have
	 * a 'dot' in it..  - phone, jan 1993.
	 */
			if (strchr(from, '.'))
				not_from_server = 0;

			line = do_notice_ctcp(from, to, line);
			if (!*line)
			{
				doing_notice = 0;
				return;
			}
			level = set_lastlog_msg_level(LOG_NOTICE);
			no_flooding = check_flooding(from, NOTICE_FLOOD, line);

			if (sed == 1 && !do_hook(ENCRYPTED_NOTICE_LIST, "%s %s %s", from, to, line))
				sed = 0;
			else
			{
				if (no_flooding)
				{
					if (type == NOTICE_LIST)
					{
						if (do_hook(type, "%s %s", from, line))
							put_it("%s-%s-%s %s", high, from, high, line);
					}
					else
					{
						if (do_hook(type, "%s %s %s", from, to, line))
							put_it("%s-%s:%s-%s %s", high, from, to, high, line);
					}
					if (beep_on_level & LOG_NOTICE)
						beep_em(1);
				}
				set_lastlog_msg_level(level);
				if (not_from_server)
					notify_mark(from, 1, 0);
			}
		}
		else 
			parse_server_notice(from, line);
	}
	else
		put_it("%s", line + 1);

	doing_notice = 0;
}

/*
 * got_initial_version_28: this is called when ircii gets the serial
 * number 004 reply.  We do this becuase the 004 numeric gives us the
 * server name and version in an easy to use fashion, and doesnt
 * rely on the syntax or construction of the 002 numeric.
 *
 * Hacked as neccesary by jfn, May 1995
 */
void 	got_initial_version_28 (char **ArgList)
{
	char *server, *version, *umodes;

	server = ArgList[0];
	version = ArgList[1];
	umodes = ArgList[2];

	if (!strncmp(version, "2.8", 3))
	{
		if (strstr(version, "mu") || strstr(version, "me"))
			set_server_version(from_server, Server_u2_8);
		else
			set_server_version(from_server, Server2_8);
	}
	else if (!strncmp(version, "2.9", 3))
		set_server_version(from_server, Server2_9);
	else if (!strncmp(version, "u2.9", 4))
		set_server_version(from_server, Server_u2_9);
	else if (!strncmp(version, "u2.10", 4))
		set_server_version(from_server, Server_u2_10);
	else if (!strncmp(version, "u3.0", 4))
		set_server_version(from_server, Server_u3_0);
	else
		set_server_version(from_server, Server2_8);

	set_server_version_string(from_server, version);
	set_server_itsname(from_server, server);
	reconnect_all_channels();
	message_from(NULL, LOG_CRAP);

	reinstate_user_modes();

	if (never_connected)
	{
		never_connected = 0;

		if (!ircrc_loaded)
		{
			char buffer[BIG_BUFFER_SIZE+1];
			strcpy(buffer, "global");

			loading_global = 1;
			load("LOAD", buffer, empty_string);
			loading_global = 0;

			/* read the .ircrc file */
			if (access(ircrc_file, R_OK) == 0 && !quick_startup)
				load("LOAD", ircrc_file, empty_string);

			ircrc_loaded = 1;
		}

		if (default_channel)
		{
			send_to_server("JOIN %s", default_channel);
			new_free(&default_channel);
		}
	}
	else if (get_server_away(from_server))
		set_server_away(from_server, get_server_away(from_server));

	update_all_status();
	do_hook(CONNECT_LIST, "%s %d %s", get_server_name(from_server),
		get_server_port(from_server), get_server_itsname(from_server));
}

int kill_message (const char *from, char *cline)
{
	char *poor_sap;
	char *bastard;
	char *path_to_bastard;
	char *reason;
	char *line;

	line = alloca(strlen(cline) + 1);
	strcpy(line, cline);

	poor_sap = next_arg(line, &line);

	/* Broken Dalnet kill doesnt append the period */
	if (!end_strcmp(poor_sap, ".", 1))
		chop(poor_sap, 1);

	/* Broken dalnet kill doesnt use "From", but "from" */
	if (my_strnicmp(line, "From ", 5))
	{
		yell("Attempted to parse an ill-formed KILL request [%s %s]",
			poor_sap, line);
		return 0;
	}
	line += 5;
	bastard = next_arg(line, &line);

	/* Fend off future broken kills */
	if (my_strnicmp(line, "Path: ", 6))
	{
		yell("Attempted to parse an ill-formed KILL request [%s %s %s]",
			poor_sap, bastard, line);
		return 0;
	}
	line += 6;
	path_to_bastard = next_arg(line, &line);
	reason = line;

	return !do_hook(KILL_LIST, "%s %s %s %s %s", from, poor_sap, bastard,
					path_to_bastard, reason);
}

