/*
 * f_antiidle.c
 * (c) fez - adds a command AWAKEN to anti-idle and a timer to send out this
 * command. Also includes an optional config file directive set::antiidle_delay
 * to set the interval for this timer.
 */

// includes
#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "proto.h"
#include "channel.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <fcntl.h>
#include "h.h"
#ifdef STRIPBADWORDS
#include "badwords.h"
#endif
#ifdef _WIN32
#include "version.h"
#endif

// module-specific defines
#define ANTIIDLE_DELAY	60
#define MSG_AWAKEN      "AWAKEN"
#define TOK_AWAKEN      NULL
#define ANTIIDLE_DIRECTIVE	"antiidle-delay"

// function declarations
DLLFUNC int f_antiidle_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
DLLFUNC int f_antiidle_config_posttest(int *errs);
DLLFUNC int f_antiidle_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
DLLFUNC int f_antiidle_config_rehash();
DLLFUNC int f_awaken(aClient *cptr, aClient *sptr, int parc, char *parv[]);
EVENT(f_antiidle);
//DLLFUNC int f_antiidle_stats(aClient *sptr, char *stats);

// global variables
static int antiidle_delay = ANTIIDLE_DELAY;	// delay in broadcast timer
static int antiidle_conf_counter = 0;	// whether read delay in conf file
ModuleInfo *AntiidleModInfo = NULL;	// for local storage of modinfo
static Hook *AntiidleHookTest = NULL;	// for config file hashing
static Hook *AntiidleHookPosttest = NULL;	//
static Hook *AntiidleHookRun = NULL;	//
static Hook *AntiidleHookRehash = NULL;	//
static Command *AwakenCmd;		// to store command hook status
Event *AntiidleEvent = NULL;		// for broadcast timer
//static Hook *AntiidleStats = NULL;	// for config/stat hook status

// a description of this module
ModuleHeader MOD_HEADER(f_antiidle)
  = {
	"f_antiidle",
	"$Id: f_antiidle.c, v1.0.2 2006/12/12 18:45:52 fez Exp $",
	"AWAKEN command, anti-idle timer.",
	"3.2.3",
	NULL
  };

// called before config test
DLLFUNC int MOD_TEST(f_antiidle)(ModuleInfo *modinfo)
{
	int ret = MOD_SUCCESS;
	AntiidleHookTest = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGTEST, f_antiidle_config_test);
	AntiidleHookPosttest = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, f_antiidle_config_posttest);
	return ret;
}

// called during module initialization
DLLFUNC int MOD_INIT(f_antiidle)(ModuleInfo *modinfo)
{
	int ret = MOD_SUCCESS;
	AntiidleModInfo = modinfo;
	antiidle_delay = ANTIIDLE_DELAY;
	AntiidleHookRun = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGRUN, f_antiidle_config_run);
	AntiidleHookRehash = HookAddEx(modinfo->handle, HOOKTYPE_REHASH, f_antiidle_config_rehash);
	AwakenCmd = CommandAdd(modinfo->handle, MSG_AWAKEN, TOK_AWAKEN, f_awaken, MAXPARA, M_USER|M_SERVER|M_SHUN|M_NOLAG|M_RESETIDLE);
	if (!AwakenCmd)
		ret = MOD_FAILED;
	return ret;
}

// called when ircd is 100% ready
DLLFUNC int MOD_LOAD(f_antiidle)(int module_load)
{
	int ret = MOD_SUCCESS;
	AntiidleEvent = EventAddEx(AntiidleModInfo->handle, "antiidle", antiidle_delay, 0, f_antiidle, NULL);
	return ret;
}

// called when unloading a module
DLLFUNC int MOD_UNLOAD(f_antiidle)(int module_unload)
{
	int ret = MOD_SUCCESS;
	CommandDel(AwakenCmd);
	EventDel(AntiidleEvent);
	HookDel(AntiidleHookTest);
	HookDel(AntiidleHookPosttest);
	HookDel(AntiidleHookRun);
	HookDel(AntiidleHookRehash);
	AwakenCmd = NULL;
	AntiidleEvent = NULL;
	AntiidleHookTest = AntiidleHookPosttest = AntiidleHookRun = AntiidleHookRehash = NULL;
	return ret;
}

// this is where we TEST the config file
DLLFUNC int f_antiidle_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
	int errors = 0;
	if (type != CONFIG_SET)
		return 0;
	if (!strcmp(ce->ce_varname, ANTIIDLE_DIRECTIVE))
	{
		if (!ce->ce_vardata)
		{
			config_error("%s:%i: set::%s without contents",
				ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
				ce->ce_varname );
			errors++;
		}
		else if (antiidle_conf_counter)
		{
			config_error("%s:%i: set::%s already defined on line %i",
				ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
				ce->ce_varname, antiidle_conf_counter );
			errors++;
		}
		else if (atoi(ce->ce_vardata) < 1)
		{
			config_error("%s:%i: set::%s must be > 0",
				ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
				ce->ce_varname );
			errors++;
		}
		else
		{
			antiidle_conf_counter = ce->ce_varlinenum;
			!antiidle_conf_counter && ++antiidle_conf_counter;
		}
		*errs = errors;
		return errors ? -1 : 1;
	}
	return 0;
}

// this is run AFTER testing the config file
DLLFUNC int f_antiidle_config_posttest(int *errs)
{
	/*
	int errors = 0;
	if (!antiidle_conf_counter)
	{
		//config_error("set::antiidle_delay is not set!");
		//errors++;
		////or...
		antiidle_delay = ANTIIDLE_DELAY;
	}
	*errs = errors;
	return errors ? -1 : 1;
	*/
	return 1;
}

// this is run when LOADING SETTINGS from the config file
DLLFUNC int f_antiidle_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
{
	if (type != CONFIG_SET)
		return 0;
	if (!strcmp(ce->ce_varname, ANTIIDLE_DIRECTIVE))
	{
		antiidle_delay = atoi(ce->ce_vardata);
		return 1;
	}
	return 0;
}

// this is run when REHASHING the config file
DLLFUNC int f_antiidle_config_rehash()
{
	antiidle_conf_counter = 0;
	return 1;
}

/*
 * f_awaken (...) - function to process awaken command
 *
 */
//DLLFUNC CMD_FUNC(f_awaken)
DLLFUNC int f_awaken(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	// code to reset idle time?
	//sendto_snomask(SNO_EYES, "received %s from %s", MSG_AWAKEN, sptr->name);
	return 0;
}

// antiidle timer event
EVENT(f_antiidle)
{
	sendto_serv_butone(&me, "%s :still alive", MSG_AWAKEN);
}

/* end of code */
