#include <string.h>
#include <stdlib.h>
#include "global.h"
#include "command.h"
#include "constants.h"
#include "window.h"

/* ----------------------------------------------------------------------- */
/* If nick is set, thing is a nick. Type is what should be ignored. Negate */
/* is what should *not* be ignored                                         */
/* ----------------------------------------------------------------------- */

typedef struct ignore_list *iptr;
struct ignore_list {
  char *thing;
  int nick, negate, ignore;
  iptr next;
};

/* List of all ignores */

iptr master_ignore = NULL;
extern server_ptr gsrv;

/* ----------------------------------------------------------------------- */
/* Check to see if a "type" of server message is being ignored             */
/* Scan the ignore list and compare the nick (or) userhost to entries      */
/* in the list. If we find a match, see if it is an ignore.. if it is,     */
/* return FALSE. If it is not, return TRUE;                                */
/* ----------------------------------------------------------------------- */

int ignore(nick, userhost, type)
  char *nick, *userhost;
  int type;
{
  iptr temp, match;
  int comp, biggest, negate, igg;
  char msg[MAXLEN];

  temp = master_ignore;
  match = NULL;
  igg = FALSE;
  biggest = -1;
  while (temp!=NULL)
  {
    if (temp->nick)
      comp = wild_match(temp->thing, nick);
    else
      comp = wild_match(temp->thing, userhost);
    if (comp>biggest)
    {
      match = temp;
      biggest = comp;
    }
    if (comp>-1)
      if (type & temp->negate) return FALSE;
    temp = temp->next;
  }

/* If nothing matched, we are not ignoreing */
  if (!match) return FALSE;

/* Else, check to see it this type of message is being ignored */
  igg = (type & match->ignore);
  return igg;
}

struct command_node lastlog_levels[] =
{
  {{"NONE"},     (char *)NONE},
  {{"PUBLIC"},   (char *)PUBLIC},
  {{"MSGS"},     (char *)MSGS},
  {{"NOTICE"},   (char *)NOTICES},
  {{"WALL"},     (char *)WALL},
  {{"WALLOP"},   (char *)WALLOP},
  {{"ACTIONS"},  (char *)ACTIONS},
  {{"DCC"},      (char *)DCC},
  {{"CRAP"},     (char *)CRAP},
  {{"ALL"},      (char *)ALL},
  {{ NULL},      (char *)NULL}
};

void show_ignore(user)
  char *user;
{
  iptr temp;

  say("*** Ignorance List:");
  for (temp=master_ignore; temp; temp=temp->next)
    if (strncasecmp(user, temp->thing, strlen(user)) == 0)
      show_level(temp->thing, temp->ignore, temp->negate, NULL);
  say("*** End of Ignorance List.");
}

void add_ignore(user, rest)
  char *user, *rest;
{
  int ignore = NONE, negate = NONE, loop, cmp;
  char type[MAXLEN], msg[MAXLEN];
  iptr front, back = NULL, walk;

  front = master_ignore;
  while (front && ((cmp = strcasecmp(front->thing, user)) < -1))
  {
    back = front;
    front = front->next;
  }
  if (cmp == 0) {
    ignore = front->ignore;
    negate = front->negate;
    if (!back) master_ignore = front->next;
    else back->next = front->next;
    free(front->thing);
    free(front);
  }
  if (!lookup_level(rest, &ignore, &negate)) {
    say("*** You must specify one of the following:");
    (void)sprintf(msg, "***     ");
    for (loop=0;lastlog_levels[loop].command;loop++)
    {
      (void)strcat(msg, lastlog_levels[loop].command);
      (void)strcat(msg, "  ");
    }
    say("%s", msg);
  } else if ((ignore==NONE) && (negate==NONE)) {
    say("*** %s removed from ignorance list", user);
  } else {
    if ((front = (iptr)malloc(sizeof(struct ignore_list))) == NULL)
    {
      say("Could not malloc for ignore!");
      return;
    }
    walk = master_ignore;
    back = NULL;
    while (walk && (strcasecmp(walk->thing, user) < 0)) {
      back = walk;
      walk = walk->next;
    }
    front->next = walk;
    if (!back) master_ignore = front;
    else back->next = front;
    front->ignore = ignore;
    front->negate = negate;
    front->thing = malloc(strlen(user) + 1);
    (void)strcpy(front->thing, user);
    if (strstr(user, "@") == NULL) front->nick = TRUE;
    else front->nick = FALSE;
    show_ignore(user);
  }
}

void user_ignore(char *string)
{
  char user[MAXLEN];

  (void)grab_word(&string, ' ', user);
  if (*string) add_ignore(user, string);
  else show_ignore(user);
}
