#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.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

// Channel Mode  Flag. Change Z to whatever you want but MUST be one character.
#define FLAG_NOREPEAT		'Z' 
#define IsNoRepeat(x)		((x)->mode.extmode & MODE_NOREPEAT)

Cmode_t				MODE_NOREPEAT = 0L;
Cmode				*ModeNoRepeat;

static char			*cb_chanmsg(aClient *, aClient *, aChannel *, char *, int);
static Hook			*HookChanMsg;

typedef struct _norepeat norepeat;
struct _norepeat {
    norepeat *prev,*next;
    aClient *cptr;
    aChannel *chptr;
    char msg[BUFSIZE];
};
norepeat *norepeat_last;

norepeat *new_norepeat(void);
void remove_norepeat(norepeat *);
norepeat *find_norepeat(aClient *,aChannel *);

ModuleHeader MOD_HEADER(NoRepeat)
  = {
	"NoRepeat",
	"v2.1",
	"+Z No repeat by DeviL - www.zemra.org",
	"3.2-b8-1",
	NULL 
    };

DLLFUNC int MOD_INIT(NoRepeat)(ModuleInfo *modinfo)
{
	CmodeInfo ModeNR;
#ifndef STATIC_LINKING
	ModuleSetOptions(modinfo->handle, MOD_OPT_PERM);
#endif
	memset(&ModeNoRepeat, 0, sizeof ModeNoRepeat);

	ModeNR.paracount	= 0;
	ModeNR.is_ok		= extcmode_default_requirechop;
	ModeNR.flag		= FLAG_NOREPEAT;
	ModeNoRepeat		= CmodeAdd(modinfo->handle, ModeNR, &MODE_NOREPEAT);

#ifndef STATIC_LINKING
        if (ModuleGetError(modinfo->handle) != MODERR_NOERROR || !ModeNoRepeat)
        {
            config_error("Error adding channel mode +%c when loading module %s: %s",
                ModeNR.flag,MOD_HEADER(NoRepeat).name,ModuleGetErrorStr(modinfo->handle
        }
#else
        if (!ModeNoRepeat)
        {
            config_error("Error adding channel mode +%c when loading module %s:",
                ModeNR.flag,MOD_HEADER(NoRepeat).name);
        }
#endif

	HookChanMsg		= HookAddPCharEx(modinfo->handle,HOOKTYPE_CHANMSG,cb_chanmsg);

	return MOD_SUCCESS;
}

DLLFUNC int MOD_LOAD(NoRepeat)(int module_load)
{
	return MOD_SUCCESS;
}

DLLFUNC int MOD_UNLOAD(NoRepeat)(int module_unload)
{
	if (ModeNoRepeat)
		CmodeDel(ModeNoRepeat);
	HookDel(HookChanMsg);

	return MOD_SUCCESS;
}

DLLFUNC char *cb_chanmsg(aClient *cptr, aClient *sptr, aChannel *chptr, char *text, int notice)
{
    static char retbuf[4096];
    norepeat *nr;

    if (!IsNoRepeat(chptr) || !MyClient(sptr))
        return text;

    nr = find_norepeat(cptr,chptr);
    if (nr == NULL)
    {
	nr = new_norepeat();
	nr->cptr = cptr;
	nr->chptr = chptr;
    }
    if (!strcmp(nr->msg,text))
	return NULL;

    strcpy(nr->msg,text);
    return text;
}

norepeat *new_norepeat(void)
{
    norepeat *nr;

    nr = (norepeat *)malloc(sizeof(norepeat));
    memset(nr,0, sizeof(norepeat));

    nr->next = norepeat_last;
    norepeat_last = nr;
    if (nr->next)
        nr->next->prev = nr;

    return nr;
}

void remove_norepeat(norepeat *nr)
{
    if (nr->prev)
        nr->prev->next = nr->next;
    else
    {
        norepeat_last = nr->next;
        if (norepeat_last)
            norepeat_last->prev = NULL;
    }
    if (nr->next)
        nr->next->prev = nr->prev;

    free(nr);
    nr = NULL;
}

norepeat *find_norepeat(aClient *cptr,aChannel *chptr)
{
    norepeat *nr;
    for (nr = norepeat_last;nr;nr = nr->next)
    {
        if ((nr->cptr == cptr) && (nr->chptr == chptr))
	    return nr;
    }
    return NULL;
}