/*
 * removeuser.c
 * (C) Christian Magnusson 2000, Email: d1mag@dtek.chalmers.se
 * This program is copyright, and covered by the Gnu Public License.
 * The Q bot.
 */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "settings.h"
#include "bottypes.h"
#include "globals.h"
#include "dl.h"

void m_removeuser(char *a);

MODULE_PUBLIC int _init_removeuser(void *a, void *b)
{
  dl_command_entry_t *dl = a;
  if(!a) return 0;

  snprintf(dl->help, MAX_COMMAND_HELP_LEN,


	   "/msg %s REMOVEUSER <#channel> <nickname>\n"\
	   "Remove a user from a channel.\nYou should use CHANLEV to view/set the flags, but this option removes all flags for a user.\n"\
	   "/msg %s REMOVEUSER #channel nick    Remove AUTHED user.\n"\
	   "/msg %s REMOVEUSER #channel #nick   Remove user (if not authed)\n"
	   , BOT_NAME, BOT_NAME, BOT_NAME);
  snprintf(dl->summary, MAX_COMMAND_SUMMARY_LEN,
	   "Remove a user from a channel.");
  dl->level = 1;
#if 0
  dl->func = m_removeuser;
#else
  dl->func = (void (*)(char*)) DL_sym(dl->val, "m_removeuser");
#endif
  return 1;
}

MODULE_PUBLIC int _remove_removeuser(char *a, char *b)
{
  remove_command("removeuser");
  return 1;
}

MODULE_PUBLIC void m_removeuser(char *a)
{
  int i;
  char channel[CHANNELLEN+1], victim[NICKLEN+2];
  unsigned int newlevel,slevel,vlevel;
  struct activeuser *u;
  struct dbaseuser *d;
  struct chanpriv *p,*q;
  struct chanopts *c;
  ListElem *el;
  int oper;

  struct dbaseuser *db;
  db = sender_au->dbuser;
  if(db) {
    log("From: %s removeuser [%s]\n", db->nick, a);
  } else
    return;

  i=0;
  strncpy(channel,getword(a,&i),CHANNELLEN);
  channel[CHANNELLEN] = '\0';
  if(!strlen(channel)) {
    say_sender("You forgot the channel parameter");
    say_sender_( "/msg %s REMOVEUSER #channel nick", BOT_NAME);
    say_sender_( "/msg %s REMOVEUSER #channel #nick", BOT_NAME);
    return;
  }

  if(channel[0]!='#') {
    say_sender( "Couldn't find that channel (must begin with '#').");
    say_sender_( "/msg %s REMOVEUSER #channel nick", BOT_NAME);
    say_sender_( "/msg %s REMOVEUSER #channel #nick", BOT_NAME);
    return;
  }
  c = findchannel(channel);
  if(!c) {
    say_sender("Couldn't find that channel");
    say_sender_( "/msg %s REMOVEUSER #channel nick", BOT_NAME);
    say_sender_( "/msg %s REMOVEUSER #channel #nick", BOT_NAME);
    return;
  }

  oper = is_oper();

  slevel = userlevelonchan_d(sender_au->dbuser, channel);
  strncpy(victim, getword(a,&i), NICKLEN+1);
  victim[NICKLEN+1] = '\0';

  if(!strlen(victim)) {
    say_sender("You forgot the nickname parameter");
    say_sender_( "/msg %s REMOVEUSER #channel nick", BOT_NAME);
    say_sender_( "/msg %s REMOVEUSER #channel #nick", BOT_NAME);
    return;
  }

  /*
    '#' will look in the global database
    ' ' will look in active userlist.
  */
  if (victim[0]!='#') {
    d = finduserfromnick(victim);
  } else {
    d = finduserfromname(victim+1);
  }

  if(!d) {
    say_sender_("Can't find that nickname. If user is known by %s, but isn't logged on, then", BOT_NAME);
    say_sender_("Try: /msg %s REMOVEUSER #chan #nickname", BOT_NAME);
    return;
  }

  vlevel = userlevelonchan_d(d, channel);

#if 0
  newlevel = vlevel;
  updatemodes(&newlevel, "-amnovt");
#else
  /* force no flags just in case.. */
  newlevel = 0;
#endif
  
  if(slevel==0) {
    if(!oper || (sender_au->auth<950)) {
      /*
	Check to see if they have a high enough level to dump userlist
      */
      say_sender( "You are not known on that channel and can't change the channelflags!");
      return;
    }
  }
	
  if(!oper && (sender_au->auth<950)) {
    if( !(slevel & (CHAN_MASTER | CHAN_OWNER)) ) {
      say_sender("You have to be master to remove any user's flags!");
      return;
    }
    if( (vlevel & CHAN_OWNER) && (!(slevel & CHAN_OWNER)) ) {
      say_sender("You have to be owner to remove an owner's flags!");
      return;
    }
    if( (vlevel & CHAN_MASTER) && (!(slevel & CHAN_OWNER)) ) {
      say_sender("You have to be owner to remove a master's flags!");
      return;
    }
  }

  c = findchannel(channel);
  if(c && c->suspended && !is_oper()) { say_sender("Channel is suspended"); return; }

  /*
    OK, the security stuff is out of the road, time to just make the
    damn change.
    Look at a users channel list and try to find victim on #channel
  */
  if(!vlevel) {
    say_sender( "Couldn't find user on that channel");
    return;
  } else {
    /*
      User is known in that channel
    */
    q = NULL;
    p = d->privs;
    while(p) {
      if(!strcasecmp(channel,p->channel)) break;
      q = p;
      p = p->next;
    }
    if(p) {
      /*
	all modes on that channel are removed for that user now.
      */
      if(q==NULL) {
	d->privs = p->next;
      } else {
	q->next = p->next;
      }
      Free(p);
      if(is_empty_channel(channel)) {
	delchannel(channel);
      }
      
      /*
	remove auth status from the activeuser->chanmodes too
	Have to search through ALL active users... sorry.. in case
	many users have authed as same userid...
      */
      el = GetHead(auser_list);
      while(el) {
	u = ((struct activeuser *)el->data);
	if(u->userid == d->userid) {
	  struct chanmod *cm, *qm;
	  /* found a user, authed with that userid... */
	  qm = NULL;
	  cm = u->chanmodes;
	  while(cm) {
	    if(!strcasecmp(channel, cm->channel)) break;
	    qm = cm;
	    cm = cm->next;
	  }
	  if(cm) {
	    if(qm==NULL) {
	      u->chanmodes = cm->next;
	    } else {
	      qm->next = cm->next;
	    }
	    Free(cm);
	  }
	}
	el = GetSucc(el);
      }
    }
  }
  say_sender("Done.");
  return;
}
