/*
 * pubhandlers.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 <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <time.h>
#include <dlfcn.h>
#include "../../settings.h"
#include "../../globals.h"
#include "../../bottypes.h"
#include "pubtab.h"

#define NAME "PUBHandlers"
#define VERSION 1.00

char *p_gettv (char *buffer, char name[10]);
MODULE_INIT _module_init(MODULE m);
MODULE_DESTROY _module_destroy(MODULE m);

MODULE_INIT _module_init(MODULE m) {
  strncpy(m->name, NAME, 20);
  strncpy(m->compiledate, __DATE__ " " __TIME__, 30);
  m->version = VERSION;  
}

MODULE_DESTROY _module_destroy(MODULE m) {

}

void p_parse (char *command, char *a, struct arm *arm)
{
  int i = 0;
  char msg[256];

  if(strcasecmp(command, "ME") == 0) return; // We don't want me commands
  if(strcasecmp(command, arm->nick) == 0) strcpy(command, "ME");
  
  while (pubtab[i].func != 0)
    {
      if (strcasecmp (pubtab[i].msg, command) == 0)
	{
	  if (userlevel(arm->parsevars->sender) >= pubtab[i].level)
	    {
	      pubtab[i].func (a, arm);
	    } else { 
	      sprintf(msg, "You don't have access to this command. If you think you should have, check that you are AUTH'd and try /msg %s IDENT", arm->nick);
	      say(arm->parsevars->sender, msg, arm);
	    }
	  return;
	}
      i++;
    }
}

void p_me (char *a, struct arm *arm) {
  char command[512];
  char arg[512];
  char tmp[512];
  struct module *m;
  void (*cmd)();

  sscanf(a, "%s", command);
  sprintf(tmp, "%s ", command);
  STR_replace_c (a, tmp, "", arg);
  
  m = findmodule("MSGHandlers");
  if(m != NULL) {

    if(strcasecmp(command, "OP") == 0) {
      if(countargs(a) == 1) sprintf(command, "%s %s", arm->parsevars->args[0], arm->parsevars->sender);
      if(countargs(a) == 2) sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_op");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "DEOP") == 0) {
      if(countargs(a) == 1) sprintf(command, "%s %s", arm->parsevars->args[0], arm->parsevars->sender);
      if(countargs(a) == 2) sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_deop");
      cmd(command, arm);
      return;
    }   
    if(strcasecmp(command, "DEVOICE") == 0) {
      if(countargs(a) == 1) sprintf(command, "%s %s", arm->parsevars->args[0], arm->parsevars->sender);
      if(countargs(a) == 2) sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_devoice");
      cmd(command, arm);
      return;
    } 
    if(strcasecmp(command, "VOICE") == 0) {
      if(countargs(a) == 1) sprintf(command, "%s %s", arm->parsevars->args[0], arm->parsevars->sender);
      if(countargs(a) == 2) sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_voice");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "CHANSET") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_chanset");
      cmd(command, arm);
      return;
    } 
    if(strcasecmp(command, "USERLEV") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_userlev");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "GREET") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_greet");
      cmd(command, arm);
      return;
    }  
    if(strcasecmp(command, "KICK") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_kick");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "BAN") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_ban");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "UNBAN") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_unban");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "WHOIS") == 0) {
      cmd = dlsym(m->fl, "m_whois");
      cmd(arg, arm);
      return;
    }
    if(strcasecmp(command, "ACCESS") == 0) {
      sprintf(command, "%s %s", arm->parsevars->args[0], arg);
      cmd = dlsym(m->fl, "m_access");
      cmd(command, arm);
      return;
    }
    if(strcasecmp(command, "IDENT") == 0) {
      cmd = dlsym(m->fl, "m_ident");
      cmd(arg, arm);
      return;
    }
  }  
#ifdef Q
  if(strcasecmp(command, "QREG") == 0) {
    if(userlevel(arm->parsevars->sender) < MASTER_TECHNICIAN) return;

    if(strcasecmp(arg, "QREG") == 0) {
      strcpy(tmp, "HELLO " Q_EMAIL " " Q_EMAIL);
      exprivmsg(Q_NICK, tmp, arm);
    }
    else {
      sprintf(command, "%s@%s", Q_NICK, Q_HOST);
      sprintf(tmp, "AUTH %s %s", arm->nick, arg);
      exprivmsg(command, tmp, arm);
      
      sprintf(tmp, "NEWPASS %s %s %s", arg, Q_PASS, Q_PASS);
      exprivmsg(Q_NICK, tmp, arm);
    }
    return;
  }
#ifdef Q_AUTOAUTH
  if(strcasecmp(command, "SYNC") == 0) {
    if(userlevel(arm->parsevars->sender) < HELPER) return;
    cmd = dlsym(m->fl, "m_sync");
    cmd(arm->parsevars->args[0], arm);
  }
#endif
#endif
}

void p_stats (char *a, struct arm *arm) {
  struct channel *c;
  char msg[512];

  c = findchannel(arm->parsevars->args[0]);
  
  if(c == NULL || c->stats == 0) sprintf(msg, "Logging and statistics are not activated on this channel.");
  else sprintf(msg, "%cStats:%c %s?cid=%i %cLogs:%c %s?cid=%i", BOLD, BOLD, STATSADDR, c->id, BOLD, BOLD, LOGADDR, c->id);
  privmsg(arm->parsevars->args[0], msg);
}

void p_peak (char *a, struct arm *arm) {
  struct channel *c;
  char msg[512];

  c = findchannel(arm->parsevars->args[0]);
  
  if(c == NULL || c->peak == 0) return;
  else sprintf(msg, "%cPeak:%c %i", BOLD, BOLD, c->peak);
#ifdef SPAMSCAN
  if(SOnChannel(c)) if(!SpamChannel(c)) say(arm->parsevars->sender, "Peak has already been asked in the last minutes. Please wait a while before asking again.", arm); 
  else { 
    privmsg(arm->parsevars->args[0], msg); 
    SpamChannelWait(c); 
  } else
#endif
  privmsg(arm->parsevars->args[0], msg);
}

void p_netstat (char *a, struct arm *arm) {
  struct channel *c;
  char msg[2048];
  short go = 0;

  if(strcmp(arm->parsevars->args[0], HOMECHAN) != 0) return;

  c = firstchan;
  
  while (c != NULL)
    {
      if(c->arm == arm) {
	if(c->ison == 0 || c->isop == 0) {
	  if(go == 0) {
	    go = 1;
	    sprintf(msg, "%cNo op/can't get in:%c ", BOLD, BOLD);
	  }

	  if(c->ison == 0) strcat(msg ,"*");
	  strcat(msg, c->name);
	  strcat(msg, " ");
	}
      }

      c = c->next;
    }
  if(go == 1) say(arm->parsevars->sender, msg, arm);
}

void p_tv (char *a, struct arm *arm) {
  FILE *pFile;
  long lSize;
  char *buffer;  
  char msg[512] = "";
  struct channel *c;
  
  c = findchannel(arm->parsevars->args[0]);
  if(c == NULL || c->tv == 0) return;

  pFile = fopen ("tv" , "r");
  if (pFile==NULL) return;
  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  rewind (pFile);
  buffer = (char*) malloc (lSize);
  if (buffer == NULL) return;

  fread (buffer,1,lSize,pFile);
  fclose (pFile);

  /* Say */
  sprintf(msg, "%cTV:%c SVT 1: %c%s%c SVT 2: %c%s%c TV3: %c%s%c TV4: %c%s%c Kanal 5: %c%s%c ZTV: %c%s%c", BOLD, BOLD, BOLD, p_gettv(buffer, "svt1"), BOLD, BOLD,  p_gettv(buffer, "svt2"), BOLD, BOLD,  p_gettv(buffer, "tv3"), BOLD, BOLD, p_gettv(buffer, "tv4"), BOLD, BOLD, p_gettv(buffer, "kanal5"), BOLD, BOLD, p_gettv(buffer, "ztv"), BOLD);

#ifdef SPAMSCAN
  if(SOnChannel(c)) if(!SpamChannel(c)) say(arm->parsevars->sender, "TV has already been asked in the last minutes. Please wait a while before asking again.", arm); 
  else {
    privmsg(arm->parsevars->args[0], msg); 
    SpamChannelWait(c); 
  } else
#endif
    privmsg(arm->parsevars->args[0], msg);

  free (buffer);
}

char *p_gettv (char *buffer, char name[10]) {
  char tmp[1000];
  char tmp2[10000];
  int i = 0;
  int j = 0;
  char *text = malloc(256);
  
  memset(text,0x0,256);
 
  sprintf(tmp, "src=\"img2/%s.gif\"", name);
  
  if(strstr(buffer, tmp) == NULL) return text;
  
  strncpy(tmp2, strstr(buffer, tmp), 10000);

  if(strstr(tmp2, "('http://") == NULL) return text;

  strncpy(tmp, strstr(tmp2, "('http://"), 1000);

  for(j = 0; tmp[i] != '\0' && tmp[i] != '>'; ++i);
  ++i;

  strncpy(tmp2, "", 1000);

  for(j = 0; tmp[i] != '\0' && tmp[i] != '<' && i < 1000; ++j) {
    tmp2[j] = tmp[i];
    ++i;
  }

  strncpy(text, tmp2, 256);
  return text;
}

void p_date (char *a, struct arm *arm) {
  time_t tim;
  char tmstr[512] = "";
  struct channel *c;
  struct tm *tmstruct;

  c = findchannel(arm->parsevars->args[0]);
  if(c == NULL || c->infobot == 0) return;

  tim = time(NULL);
  tmstruct = localtime(&tim);
  strftime(tmstr, 512, "It is %A the %dth of %B. The time is: %H:%M:%S.", tmstruct);

  privmsg(arm->parsevars->args[0], tmstr);
}

void p_vote (char *a, struct arm *arm) {
  /* Handle !vote, voting commands. 
   * !vote start <time(minutes)> <question>, will start a vote. CHAN_OP required. Max question length: 255 chars
   * !vote stop, will stop a vote. Vote founder or CHAN_MASTER 
   * !vote yes, will vote yes
   * !vote no, will vote no
   */

  char command[512];
  char arg[512];
  char tmp[512];
  int i, j;
  struct vote *vote;
  struct activeuser *u;
  struct channel *c;
  if(!checkargs(1, 1, a, arm)) return;

  sscanf(a, "%s", command);
  sprintf(tmp, "%s ", command);
  STR_replace_c (a, tmp, "", arg);
  
  c = findchannel(arm->parsevars->args[0]);

  if(c == NULL) {
    if(arm->id == 1) say(arm->parsevars->sender, "This is homechan, go vote somewhere else.", arm);
    return;
  } else if(c->vote != 1) {
    say(arm->parsevars->sender, "Sorry, but this channel doesen't have vote enabled (chanset +vote).", arm);
    return;
  }

  if(strcasecmp(command, "START") == 0) {
    if(!checkargs(3, 1, a, arm)) return;

    for(i = 0; a[i] != ' '; ++i);
    ++i;
    for(; a[i] != ' '; ++i);
    ++i;
    
    strncpy(tmp, "", 512);

    j = 0;
    while (a[i] != '\0' && j < 510) {
      tmp[j] = a[i];
      ++i;
      ++j; 
    }
   
    if(strlen(tmp) > 255) {
      say(arm->parsevars->sender, "Sorry, the question cannot be longer than 255 characters.", arm);
      return;
    }
    
    sscanf(a, "%s %i", command, &i); 

    if(i > 3600*24 || i < 1) {
      say(arm->parsevars->sender, "Time value is out of range. Time should be in minutes and in the range of 1 minute to 24 hours.", arm);
      return;
    }

    if((vote = AllocateVote(c)) == NULL) {
      say(arm->parsevars->sender, "There is already a vote active for that channel.", arm);
      return;
    }

    strncpy(vote->question, tmp, 255);
    vote->asker = findauser(arm->parsevars->sender)->userid;
    vote->expiretime = time(NULL) + i*60;

    /* Announce vote into channel */

    snprintf(tmp, 512, "A vote has been started by: %c%s%c. The question is: %c%s%c Type %c!vote yes%c to vote yes and %c!vote no%c to vote no.", BOLD, arm->parsevars->sender, BOLD, BOLD, vote->question, BOLD, BOLD, BOLD, BOLD, BOLD);
    privmsg(arm->parsevars->args[0], tmp);

  } else if(strcasecmp(command, "STOP") == 0) {
    /* Stop the vote */

    if((vote = c->votestruct) == NULL) {
      say(arm->parsevars->sender, "There is no vote going on in here.", arm);
      return;
    }

    u = findauser(arm->parsevars->sender);
    
    if(vote->asker == u->userid || chanuserlevel(arm->parsevars->sender, arm->parsevars->args[0]) >= CHAN_MASTER) {
      if(vote->yes > vote->no) snprintf(tmp, 512, "Vote stopped. %cYes%c won with %c%i%c votes against %c%i%c.", BOLD, BOLD, BOLD, vote->yes, BOLD, BOLD, vote->no, BOLD);
      else if(vote->no > vote->yes) snprintf(tmp, 512, "Vote stopped. %cNo%c won with %c%i%c votes against %c%i%c.", BOLD, BOLD, BOLD, vote->no, BOLD, BOLD, vote->yes, BOLD);
      else if(vote->no == vote->yes) snprintf(tmp, 512, "Vote stopped. Vote ended in tie with %c%i%c yes and no votes.", BOLD, vote->yes, BOLD);
      privmsg(arm->parsevars->args[0], tmp);

      FreeVote(c);
      
    } else say(arm->parsevars->sender, "Not enough access.", arm);
  } else if(strcasecmp(command, "YES") == 0) {
    /* Vote yes */

   if((vote = c->votestruct) == NULL) {
      say(arm->parsevars->sender, "There is no vote going on in here.", arm);
      return;
    }

   u = findauser(arm->parsevars->sender);
   
   for(i = 0; i <= vote->lastvid; ++i) {
     if(vote->voted[i] == u) {
       say(arm->parsevars->sender, "You have already voted in this vote.", arm);
       return;
     }
   }
   ++vote->lastvid;
   vote->voted[vote->lastvid] = u;

   ++vote->yes;
   
   say(arm->parsevars->sender, "Voted yes.", arm);

  } else if(strcasecmp(command, "NO") == 0) {
    /* Vote no */

   if((vote = c->votestruct) == NULL) {
      say(arm->parsevars->sender, "There is no vote going on in here.", arm);
      return;
    }

   u = findauser(arm->parsevars->sender);
   
   for(i = 0; i <= vote->lastvid; ++i) {
     if(vote->voted[i] == u) {
       say(arm->parsevars->sender, "You have already voted in this vote.", arm);
       return;
     }
   }

   ++vote->lastvid;
   vote->voted[vote->lastvid] = u;

   ++vote->no;

   say(arm->parsevars->sender, "Voted no.", arm);
  } else if(strcasecmp(command, "STATUS") == 0) {
    /* Vote status */
  
    if((vote = c->votestruct) == NULL) {
      say(arm->parsevars->sender, "There is no vote going on in here.", arm);
      return;
    }
    if(vote->yes > vote->no) snprintf(tmp, 512, "Vote question: %c%s%c %cYes%c is ahead with %c%i%c votes against %c%i%c. Vote with !vote yes and !vote no", BOLD, vote->question, BOLD, BOLD, BOLD, BOLD, vote->yes, BOLD, BOLD, vote->no, BOLD);
      else if(vote->no > vote->yes) snprintf(tmp, 512, "Vote question: %c%s%c %cNo%c is ahead with %c%i%c votes against %c%i%c. Vote with !vote yes and !vote no", BOLD, vote->question, BOLD, BOLD, BOLD, BOLD, vote->no, BOLD, BOLD, vote->yes, BOLD);
      else if(vote->no == vote->yes) snprintf(tmp, 512, "Vote question: %c%s%c Vote is in tie with %c%i%c yes and no votes.", BOLD, vote->question, BOLD, BOLD, vote->no, BOLD);

      privmsg(arm->parsevars->args[0], tmp);

      snprintf(tmp, 512, "The vote will end in %li minute(s). Vote with %c!vote yes%c and %c!vote no%c", (vote->expiretime - time(NULL))/60, BOLD, BOLD, BOLD, BOLD);
      privmsg(arm->parsevars->args[0], tmp);
  }
}
 

void p_showcommands (struct arm *arm) {
  int i = 0, j;
  char buffer[512];

  while (pubtab[i].func != 0)
    {
      if (pubtab[i].level <= userlevel (arm->parsevars->sender))
	{

	  memset (buffer, 0, 512);
	  sprintf(buffer, "%cPublic:%c ", BOLD, BOLD);
	 
	  if(strcmp(pubtab[i].msg, "ME") == 0) strncat (buffer, arm->nick, 256); 
	  else strncat (buffer, pubtab[i].msg, 256);

	  strcat (buffer, " ");
	  strncat (buffer, pubtab[i].summary, 200);

	  j = strlen (buffer);
	  sprintf (buffer + j, " - level %d.", pubtab[i].level);
	  dumpmessage (arm->parsevars->sender, buffer);
	}
      i++;
    }
}

void p_help (char *a, struct arm *arm)
{
  int i;
  char send[4096];

  i = 0;
  while (pubtab[i].func != 0)
    {
      if (strcasecmp (a, pubtab[i].msg) == 0)
	{
	  sprintf(send, pubtab[i].help, arm->nick);
	  dumpmessage (arm->parsevars->sender, send);  
	  return;
	}
      i++;
    }

  sprintf(send, "No help found on that topic. Try /msg %s SHOWCOMMANDS.", arm->nick);
  say (arm->parsevars->sender, send, arm);
}
