/*
 * irccommands.c
 * (C) Peter Salanki 2002
 * This program is copyright, and covered by the Gnu Public License.
 * The Natasha bot.
 * sorcer@linux.se
 */

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <dlfcn.h>
#include <pthread.h>

#include "globals.h"
#include "bottypes.h"

void settopic (char *channel, char *topic)
{

  char msg[512];
  
  snprintf(msg, 512, "TOPIC %s :%s\n\r", channel, topic);
  putserver(msg, findchannel(channel)->arm);
}


void puttime (struct arm *a)
{
  char buffer[32];
  sprintf (buffer, " %ld ", (long) time (0));
  putserver (buffer, a);
}

void op (char *channel, char *nick)
{
  char msg[512];

  snprintf(msg, 512, "MODE %s +o %s\n\r", channel, nick);
#ifdef MAIN
  if(strcmp(HOMECHAN, channel) != 0) putserver (msg, findchannel(channel)->arm);
  else putserver (msg, firstarm);
#else
  putserver (msg, findchannel(channel)->arm);
#endif
}

void deop (char *channel, char *nick)
{
  char msg[512];

  snprintf(msg, 512, "MODE %s -o %s\n\r", channel, nick);
  putserver (msg, findchannel(channel)->arm);
}

void voice (char *channel, char *nick)
{
  char msg[512];

  snprintf(msg, 512, "MODE %s +v %s\n\r", channel, nick);

#ifdef MAIN
  if(strcmp(HOMECHAN, channel) != 0) putserver (msg, findchannel(channel)->arm);
  else putserver (msg, firstarm);
#else
  putserver (msg, findchannel(channel)->arm);
#endif
}

void devoice (char *channel, char *nick)
{
  char msg[512];

  snprintf(msg, 512, "MODE %s -v %s\n\r", channel, nick);
  putserver (msg, findchannel(channel)->arm);
}

void invite (struct channel *c, char *nick)
{
  char msg[512];

  snprintf(msg, 512, "INVITE %s %s\n\r", nick, c->name);
  putserver (msg, c->arm);
}

void kick (char *channel, char *nick, char reason[])
{
  char msg[512];
  
  snprintf(msg, 512, "KICK %s %s :%s\n\r", channel, nick, reason);

#ifdef MAIN
  if(strcmp(HOMECHAN, channel) != 0) putserver (msg, findchannel(channel)->arm);
  else putserver (msg, firstarm);
#else
  putserver (msg, findchannel(channel)->arm);
#endif				       
}

void nick (char *nick, struct arm *a)
{
 
  putserver ("NICK ", a);
  putserver (nick, a);
  putserver ("\n\r", a);
  
}

void joinchannel (struct channel *c)
{
  char query[512];

  putserver ("JOIN ", c->arm);
  putserver (c->name, c->arm);

  if(strcmp(c->key, "") != 0) {
    putserver(" ", c->arm);
    putserver(c->key, c->arm);
  }
  putserver ("\n\r", c->arm);

  c->ison = 0; // Assume we are NOT on the channel
 
  ++c->arm->channels;
  
  sprintf(query, "UPDATE `arms` SET `channels` = '%i' WHERE `id` = '%i'", c->arm->channels, c->arm->id);
  dbquery(query);
  EndDbQuery();
}


void rejoinchannel (char channame[CHANNELLEN], struct arm *a)
{

  struct channel *c;

  c = findchannel(channame);

  putserver ("JOIN ", a);
  putserver (channame, a);
  
  if(c != NULL && strcmp(c->key, "") != 0) {
    putserver(" ", a);
    putserver(c->key, a);
  } 
#ifdef SAFEHOME
  else if (c == NULL) {
    putserver(" ", a);
    putserver(homekey, a);    
  }
#endif
  
  putserver ("\n\r", a);
  
  
  if(c != NULL) c->ison = 0; // Assume we are NOT on the channel
 
}

void who (struct channel *c) {
  /* Make a WHO and add all users. */
  
  char who[CHANNELLEN+40];

  sprintf(who, "WHO %s\n\r", c->name);
  putserver (who, c->arm);

  c->isop = 2; // Assume we have ops
}

void cyclechannel (struct channel *c, char *reason) {
  /* Function to cycle a channel */

  char msg[512];
  
  /* First we part */
  sprintf(msg, "PART %s :%s\n\r", c->name, reason);
  putserver (msg, c->arm);  

  OutOfChannel(c); /* Delete activechanusers and stuff */
  
  /* Then we rejoin */
  rejoinchannel (c->name, c->arm);
}

void partchannel (struct channel *c, char reason[])
{
  char msg[512];
  char query[512];

  sprintf(msg, "PART %s :%s\n\r", c->name, reason);
  putserver (msg, c->arm);
  
  --c->arm->channels;
  
  sprintf(query, "UPDATE `arms` SET `channels` = '%i' WHERE `id` = '%i'", c->arm->channels, c->arm->id);

  dbquery(query);
  EndDbQuery();
}

void say (char *victim, char *words, struct arm *a)
{
  char msg[512];
#ifdef CNOTICE
  struct aculink *aculink;
  struct activeuser *u;
  
  u = findauser(victim);
  if(u != NULL) {
    aculink = u->firstlink;
    
    while (aculink != NULL)
      {
	if(aculink->link->channel->isop == 1 && aculink->link->channel->arm == a) {
	  snprintf(msg, 512, "CNOTICE %s %s :%s\n\r", victim, aculink->link->channel->name, words);
	  putserver(msg, aculink->link->channel->arm);
	  return;
	}
	aculink = aculink->next;
      }
  }
#endif

  // No optimal CNOTICE possible, use normal notice
  sprintf(msg, "NOTICE %s :%s\n\r", victim, words);
  putserver(msg, a); // The best arm
}

void bestsay (char *victim, char *words)
{
  char msg[512];
  
  snprintf(msg, 512, "NOTICE %s :%s\n\r", victim, words);
  if(victim[0] == '#') putserver(msg, findchannel(victim)->arm); // The bot which is on that channel
  else putserver(msg, bestarm()); // The best arm
}

#ifdef CNOTICE
void cnotice (char *victim, char *words) {
  char msg[512];
  struct aculink *aculink;
  struct activeuser *u;
  
  u = findauser(victim);
  if(u != NULL) {

    aculink = u->firstlink;
    
    while (aculink != NULL)
      {
	if(aculink->link->channel->isop == 1) {
	  snprintf(msg, 512, "CNOTICE %s %s :%s\n\r", victim, aculink->link->channel->name, words);
	  putserver(msg, aculink->link->channel->arm);
	  return;
	}
	aculink = aculink->next;
      }
    
  }

  // No CNOTICE possible, use normal notice
  bestsay(victim, words); // The best arm
}
#endif

void serverpong(char data[], struct arm *a) {
  int i, u;
  char ping[15];
  
  i = u =0;
  while (data[i] != ':') ++i;
  ++i;

  while ((ping[u] = data[i]) != '\0') {
    ++i;
    ++u;
  }
  puttoserver ("PONG :", a);
  puttoserver (ping, a);
  puttoserver ("\n\r", a);
}

void privmsg (char *victim, char *words)
{
  char msg[512];

  snprintf(msg, 512, "PRIVMSG %s :%s\n\r", victim, words);
  if(victim[0] == '#') {
    if(strcmp(victim, HOMECHAN) == 0) putserver(msg, bestarm());
    else putserver(msg, findchannel(victim)->arm);
  } else putserver(msg, bestarm());
}

void exprivmsg (char *victim, char *words, struct arm *a)
{
  char msg[512];

  snprintf(msg, 512, "PRIVMSG %s :%s\n\r", victim, words);
  putserver(msg, a);
}

#ifdef L
void l_getop(struct channel *c) {
  char msg[256+CHANNELLEN];
  
  snprintf(msg, 256+CHANNELLEN, "OP %s", c->name);
  exprivmsg(L_NICK, msg, c->arm);
}

void l_invite(struct channel *c) {
  char msg[256+CHANNELLEN];
  
  snprintf(msg, 256+CHANNELLEN, "INVITE %s", c->name);
  exprivmsg(L_NICK, msg, c->arm);
}

void l_clearbans(struct channel *c) {
  char msg[256+CHANNELLEN];
  
  snprintf(msg, 256+CHANNELLEN, "unbanall %s", c->name);
  exprivmsg(L_NICK, msg, c->arm);
}
#endif

#ifdef Q
void o_requestop(struct channel *c) {
  char msg[256+CHANNELLEN];
  
  snprintf(msg, 256+CHANNELLEN, "REQUESTOP %s", c->name);
  exprivmsg("O", msg, c->arm);
}
#endif

void act (struct channel *c, char *words)
{
  char buffer[512];

  snprintf(buffer, 512, "ACTION %s", words);
  ctcp (c->name, buffer, c->arm);
}

void ctcp (char *victim, char *what, struct arm *a)
{ 
  putserver ("PRIVMSG ", a);
  putserver (victim, a);
  putserver (" :\01", a);
  putserver (what, a);
  putserver ("\01", a);
  putserver ("\n\r", a);
  
}

void ctcpreply (char *victim, char *what, struct arm *a)
{
  
  putserver ("NOTICE ", a);
  putserver (victim, a);
  putserver (" :\01", a);
  putserver (what, a);
  putserver ("\01", a);
  putserver ("\n\r", a);
}


void pong (struct arm *a)
{
  char msg[50];
  char buffer[32];
  sprintf (buffer, " %ld ", (long) time (0));
  sprintf(msg, "PONG :%s\n\r", buffer);
  putserver(msg, a);
}

void dumpmessage (char *victim, char *message)
{
  char buffer[512];
  int i, j;
  i = 0;
  j = 0;
  while (i < strlen (message))
    {
      j = 0;
      while ((message[i] != '\n') && (j < 512) && (message[i]))
	{
	  buffer[j] = message[i];
	  j++;
	  i++;
	}
      buffer[j] = 0;
      bestsay(victim, buffer);
      i++;
    }
}
