/* MemoServ IGNORE module.
 * Written by Yusuf Iskenderoglu <uhc0@stud.uni-karlsruhe.de>
 *
 * IRC Services is copyright (c) 1996-2002 Andrew Church.
 *     E-mail: <achurch@achurch.org>
 * Parts written by Andrew Kempe and others.
 * This program is free but copyrighted software; see the file COPYING for
 * details.
 */

#include "services.h"
#include "modules.h"
#include "conffile.h"
#include "language.h"
#include "commands.h"
#include "modules/nickserv/nickserv.h"
#include "modules/operserv/operserv.h"
#include "memoserv.h"

/*************************************************************************/

static Module *module;
static Module *module_memoserv;

static int MSIgnoreMax;

/*************************************************************************/

static void do_ignore(User *u);

static Command cmds[] = {
    { "IGNORE",       do_ignore, NULL,  MEMO_HELP_IGNORE,     -1,-1},
    { NULL }
};

/*************************************************************************/
/*************************** Callback routines ***************************/
/*************************************************************************/

/* Check whether the sender is allowed to send to the recipient (i.e. is
 * not being ignored by the recipient).
 */

static int check_if_ignored(int ischan, void *who, const char *whoname,
			    User *sender, char *text)
{
    NickGroupInfo *ngi = who;
    int i;

    if (ischan || !ngi)
	return 0;
    ARRAY_FOREACH (i, ngi->ignore) {
	if (match_wild_nocase(ngi->ignore[i], sender->nick)
	 || match_usermask(ngi->ignore[i], sender)
	) {
	    notice_lang(s_MemoServ, sender, MEMO_X_GETS_NO_MEMOS, whoname);
	    return 1;
	}
    }
    return 0;
}


/*************************************************************************/
/*************************** Command functions ***************************/
/*************************************************************************/

/* Handle the MemoServ IGNORE command. */

void do_ignore(User *u)
{
    char *cmd = strtok(NULL, " ");
    char *mask = strtok(NULL, " ");
    NickGroupInfo *ngi = NULL;
    NickInfo *ni;
    int i;

    if (cmd && mask && stricmp(cmd,"LIST") == 0 && is_services_admin(u)) {
	if (!(ni = get_nickinfo(mask))) {
	    notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, mask);
	} else if (ni->status & NS_VERBOTEN) {
	    notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, mask);
	} else if (!(ngi = get_ngi(ni))) {
	    notice_lang(s_MemoServ, u, INTERNAL_ERROR);
	} else if (ngi->ignore_count == 0) {
	    notice_lang(s_MemoServ, u, MEMO_IGNORE_LIST_X_EMPTY, mask);
	} else {
	    notice_lang(s_MemoServ, u, MEMO_IGNORE_LIST_X, mask);
	    ARRAY_FOREACH (i, ngi->ignore)
		notice(s_MemoServ, u->nick, "    %s", ngi->ignore[i]);
	}

    } else if (!cmd || ((stricmp(cmd,"LIST")==0) && mask)) {
	syntax_error(s_MemoServ, u, "IGNORE", MEMO_IGNORE_SYNTAX);

    } else if (!(ngi = u->ngi) || ngi == NICKGROUPINFO_INVALID) {
	notice_lang(s_MemoServ, u, NICK_NOT_REGISTERED);

    } else if (!user_identified(u)) {
	notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_MemoServ);

    } else if (stricmp(cmd, "ADD") == 0) {
	if (!mask) {
	    syntax_error(s_MemoServ, u, "IGNORE", MEMO_IGNORE_ADD_SYNTAX);
	    return;
	}
	if (ngi->ignore_count >= MSIgnoreMax) {
	    notice_lang(s_MemoServ, u, MEMO_IGNORE_LIST_FULL);
	    return;
	}
	ARRAY_FOREACH (i, ngi->ignore) {
	    if (stricmp(ngi->ignore[i], mask) == 0) {
		notice_lang(s_MemoServ, u,
			MEMO_IGNORE_ALREADY_PRESENT, ngi->ignore[i]);
		return;
	    }
	}
	ARRAY_EXTEND(ngi->ignore);
	ngi->ignore[ngi->ignore_count-1] = sstrdup(mask);
	put_nickgroupinfo(ngi);
	notice_lang(s_MemoServ, u, MEMO_IGNORE_ADDED, mask);

   } else if (stricmp(cmd, "DEL") == 0) {
	if (!mask) {
	    syntax_error(s_MemoServ, u, "IGNORE", MEMO_IGNORE_DEL_SYNTAX);
	    return;
	}
	ARRAY_SEARCH_PLAIN(ngi->ignore, mask, strcmp, i);
	if (i == ngi->ignore_count)
	    ARRAY_SEARCH_PLAIN(ngi->ignore, mask, stricmp, i);
	if (i == ngi->ignore_count) {
	    notice_lang(s_MemoServ, u, MEMO_IGNORE_NOT_FOUND, mask);
	    return;
	}
	notice_lang(s_MemoServ, u, MEMO_IGNORE_DELETED, mask);
	free(ngi->ignore[i]);
	ARRAY_REMOVE(ngi->ignore, i);
	put_nickgroupinfo(ngi);

    } else if (stricmp(cmd, "LIST") == 0) {
	if (ngi->ignore_count == 0) {
	    notice_lang(s_MemoServ, u, MEMO_IGNORE_LIST_EMPTY);
	} else {
	    notice_lang(s_MemoServ, u, MEMO_IGNORE_LIST);
	    ARRAY_FOREACH (i, ngi->ignore)
		notice(s_MemoServ, u->nick, "    %s", ngi->ignore[i]);
	}

    } else {
	syntax_error(s_MemoServ, u, "IGNORE", MEMO_IGNORE_SYNTAX);
    }
}

/*************************************************************************/
/***************************** Module stuff ******************************/
/*************************************************************************/

const int32 module_version = MODULE_VERSION_CODE;

ConfigDirective module_config[] = {
    { "MSIgnoreMax",      { { CD_POSINT, CF_DIRREQ, &MSIgnoreMax } } },
    { NULL }
};


/*************************************************************************/

int init_module(Module *module_)
{
    module = module_;

    module_memoserv = find_module("memoserv/main");
    if (!module_memoserv) {
	module_log("Main MemoServ module not loaded");
	return 0;
    }
    use_module(module_memoserv);

    if (!register_commands(module_memoserv, cmds)) {
	module_log("Unable to register commands");
	exit_module(0);
	return 0;
    }

    if (!add_callback_pri(module_memoserv, "receive memo",
			  check_if_ignored, MS_RECEIVE_PRI_CHECK)
    ) {
	exit_module(0);
	return 0;
    }
    return 1;
}

/*************************************************************************/

int exit_module(int shutdown_unused)
{
#ifdef CLEAN_COMPILE
    shutdown_unused = shutdown_unused;
#endif

    if (module_memoserv) {
 	remove_callback(module_memoserv, "receive memo", check_if_ignored);
	unregister_commands(module_memoserv, cmds);
	unuse_module(module_memoserv);
	module_memoserv = NULL;
    }

    return 1;
}

/*************************************************************************/
