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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <mysql/mysql.h>
#include <string.h>
#include "../src/settings.h"

#define ROWSPERQUERY 100

void tomirc(char *action, char *nick, char *msg, char *time, char *chan);
void convchan(int cid, char *chan);

void servicedbconnect (void);
int remotedbconnect (char *server, int port, char *user, char *pass, char *db);

void dbquery (char *query);
void servicedbquery (char *query);
void remotedbquery (char *query);
void dbconnect (void);
char *escapequery (char *query);

MYSQL mysql, *sock, servicemysql, *servicesock, remotemysql, *remotesock;
MYSQL_RES *res, *serviceres, *remoteres;
MYSQL_ROW row, servicerow, remoterow;
FILE *log;
char tmp[1024];

void dbconnect (void) {
  if (!(sock = mysql_real_connect(&mysql,MYSQL_STATSSERVER,MYSQL_STATSUSER,MYSQL_STATSPASS,MYSQL_STATSDB,3306,NULL,0)))
  {
    fprintf(stderr,"Couldn't connect to MySQL server!\n%s\n\n", mysql_error(&mysql));
    perror("");     
    exit(1);
  }
}

void servicedbconnect (void) {
  if (!(servicesock = mysql_real_connect(&servicemysql,MYSQL_SERVER,MYSQL_USER,MYSQL_PASS,MYSQL_DB,MYSQL_PORT,NULL,0)))
  {
    fprintf(stderr,"Couldn't connect to MySQL server!\n%s\n\n", mysql_error(&servicemysql));
    perror("");
    exit(1);
  }
}

int remotedbconnect (char *server, int port, char *user, char *pass, char *db) {
  if (!(remotesock = mysql_real_connect(&remotemysql,server,user,pass,db,port,NULL,0)))
  {
    fprintf(stderr,"Couldn't connect to MySQL server!\n%s\n\n", mysql_error(&remotemysql));
    perror("");
    return -1;
  } else return 1;
}

void dbquery (char *query) {

  if(mysql_query(sock, query))
    {
      printf("Query failed (%s)\n", mysql_error(sock));
      printf("Query: %s\n", query);
    
    } else res = mysql_store_result(sock);
}

void servicedbquery (char *query) {

  if(mysql_query(servicesock, query))
    {
      printf("Query failed (%s)\n", mysql_error(servicesock));
    
    } else serviceres = mysql_store_result(servicesock);
}

void remotedbquery (char *query) {

  if(mysql_query(remotesock, query))
    {
      printf("Query failed (%s)\n", mysql_error(remotesock));
    
    } else remoteres = mysql_store_result(remotesock);
}

char *escapequery (char *query) {
  
  char *escaped = malloc(2*strlen(query));
  mysql_real_escape_string(&mysql, escaped, query, strlen(query));
  
  return escaped;
}

int main (int argc, char **argv)
{
  char query[MAX_QUERY+1024];
  char *biginsert;
  char tmpnick[NICKLEN*2];
  char msg[1024];
  time_t updatetime;
  long htmlsize;
  FILE *htmlfile, *pisgconf;
  char *htmlbuffer, *bigquery, *htmlbufferparsed;
  div_t divresult;
  int mqid;

  printf("Natasha log fetcher and stats generator v1.0.\nStats will be updated every: %d hour.\n", STATS_UPDATE_TIME);
  
  while(1) {

    printf("\nNew stats run.\n"); 

    updatetime = time(NULL);

    /* Clean up and open pisg config */
    sprintf(query, "rm %s*.html && rm *.mrc", PISG);
    system(query);
  
    sprintf(query, "%spisg.cfg", PISG);
    pisgconf = fopen(query, "w");
  
    /* Write pisg header */
    fprintf(pisgconf, "#Pisg config generated by Natasha log fetcher and stats generator (a part of The Natasha Project).\n<set foul=\"ass bitch fuck jävlar fan hora fitta\" maintainer=\"%s\">\n#Here starts channel configs.\n\n", BOTHOUSE);

    dbconnect();
    servicedbconnect();

    servicedbquery("SELECT `nick` FROM `arms`");
    
    while((servicerow = mysql_fetch_row(serviceres))) {
      fprintf(pisgconf, "<user nick=\"%s\" ignore=\"y\">\n", servicerow[0]);
  }
#ifdef Q
    fprintf(pisgconf, "<user nick=\"%s\" ignore=\"y\">\n", Q_NICK);
#ifdef L
    fprintf(pisgconf, "<user nick=\"%s\" ignore=\"y\">\n", L_NICK);
#endif
#endif
    servicedbquery("SELECT `id`,`name`,`statsdb_ip`,`statsdb_port`,`statsdb_user`,`statsdb_pass`,`statsdb_db` FROM `services`");

    while((servicerow = mysql_fetch_row(serviceres))) {

      printf("Connectig to service: %s.\n", servicerow[1]); 
      if((remotedbconnect(servicerow[2], atoi(servicerow[3]), servicerow[4], servicerow[5], servicerow[6]))) {
  
	/* Now we transfer the logs */
	printf("Transferring logs.\n");
	remotedbquery("SELECT `cid`,`action`,`nick`,`username`,`host`,`uid`,`msg`,`time` FROM `log`");

	mqid = 0;

	biginsert = malloc(512*ROWSPERQUERY); // Malloc

	while((remoterow = mysql_fetch_row(remoteres))) {
	  strncpy(msg, "", 1024);
	  strncpy(tmpnick, "", NICKLEN);

	  mysql_real_escape_string(&remotemysql, tmpnick, remoterow[2], strlen(remoterow[2]));
	  mysql_real_escape_string(&remotemysql, msg, remoterow[6], strlen(remoterow[6]));
	  
	  if (mqid == 0) {
	    sprintf(biginsert, "INSERT INTO `log` (`cid`, `action`, `nick`, `username`, `host`, `uid`, `msg`, `time`) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", remoterow[0], remoterow[1], tmpnick, escapequery(remoterow[3]), remoterow[4], remoterow[5], msg, remoterow[7]);
	  } else if (mqid == ROWSPERQUERY) {
	    sprintf(query, ", ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", remoterow[0], remoterow[1], tmpnick, escapequery(remoterow[3]), remoterow[4], remoterow[5], msg, remoterow[7]); 
	    strcat(biginsert, query);	   
	    
	    mysql_query(sock, biginsert);
	    mqid = -1;
	    //	    printf("len: %i)\n", strlen(biginsert));
	  } else {
	    sprintf(query, ", ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", remoterow[0], remoterow[1], tmpnick, escapequery(remoterow[3]), remoterow[4], remoterow[5], msg, remoterow[7]); 
	    strcat(biginsert, query);
	  }
	  ++mqid;
	}
	
	if (mqid > 0) {
	  mysql_query(sock, biginsert);
	  mqid = 0;
	}
	
	free(biginsert); // Free

	remotedbquery("DELETE FROM `log`");

	mysql_close(remotesock);
      }
    }

    /* Now we are going to make mIRC logs for all channels */
    printf("Generateing mIRC logs of all channel logs.\n");

    /* First we get all channels and add to pisg config and generate smIRC logs */
    servicedbquery("SELECT `id`,`name` FROM `channels` WHERE `stats` = 1");
    
    while((servicerow = mysql_fetch_row(serviceres))) {
	  fprintf(pisgconf, "<channel=\"%s\" logfile=\"../%i.mrc\">\n\tformat=\"mIRC\"\n\tnetwork=\"%s\"\n\toutputfile=\"%i.html\"\n</channel>\n\n", servicerow[1], atoi(servicerow[0]), NETWORK, atoi(servicerow[0]));
	 
	  convchan(atoi(servicerow[0]), servicerow[1]);
    }
    
    fclose(pisgconf); /* We close the pisg config */

    /* Free */
    mysql_free_result(res);
    mysql_free_result(serviceres);
    mysql_free_result(remoteres);
	
    /* Run pisg and create the stats */
    printf("Running pisg.\n");
    sprintf(query, "cd %s && ./pisg > pisg.log && cd ../", PISG);
    system(query);

    /* Read all HTML files and add them to SERVICE-DB */
    printf("Inserting pisg outpout to database.\n");

    servicedbquery("DELETE FROM `stats`");

    servicedbquery("SELECT `id`,`name` FROM `channels` WHERE `stats` = 1");
    
    while((servicerow = mysql_fetch_row(serviceres))) {
      sprintf(query, "%s%i.html", PISG, atoi(servicerow[0]));
      htmlfile = fopen(query, "rb");

      if(htmlfile != NULL) {
	fseek (htmlfile, 0, SEEK_END);
	htmlsize = ftell(htmlfile);
	rewind(htmlfile); 

	/* Some mallocs */
	htmlbuffer = (char*) malloc(htmlsize);
	htmlbufferparsed = (char*) malloc(htmlsize+htmlsize);
	bigquery = (char*) malloc(htmlsize+htmlsize+MAX_QUERY);
	if(htmlbuffer != NULL && bigquery != NULL) {   
	  fread(htmlbuffer,1,htmlsize,htmlfile);
       
	  /* Let's add to database */
	  mysql_real_escape_string(&servicemysql, htmlbufferparsed, htmlbuffer, htmlsize);
	  sprintf(bigquery, "INSERT INTO `stats` (`name`, `cid`, `html`) VALUES ('%s', '%d', '%s')", servicerow[1], atoi(servicerow[0]), htmlbufferparsed);

	  mysql_query(servicesock, bigquery);
	  
	  /* We free some memory */
	  free(htmlbuffer);
	  free(htmlbufferparsed);
	  free(bigquery);
	} else printf("Malloc error.\n");
	
	fclose(htmlfile);
      }
    }

    updatetime = (time(NULL) - updatetime);
    divresult = div(updatetime, 60);

    /* Now we updatet some info */
    sprintf(query, "UPDATE `info` SET `stats_lastupdate` = '%i', `stats_time` = '%i'", time(NULL), updatetime);
    servicedbquery(query);

    /* Now we close som MySQL connections and free some memory*/
    mysql_close(servicesock);
    mysql_close(sock);

    mysql_free_result(serviceres);
    mysql_free_result(remoteres);

    printf("Stats run completd in: %i minutes.\n", divresult.quot);
    sleep(STATS_UPDATE_TIME*3600); // Now we ZZzzz till next run.
    
    /* This is only some lazy code to solve this bug, sohould be properly fixed */
    
    system("sleep 10 && ./stats &");
    exit(0);
  }

  return 0;
}

void convchan(int cid, char *chan) {
  char query[MAX_QUERY];

  /* Open the mIRC log */
  sprintf(query, "%i.mrc", cid);
  log = fopen(query, "w");
  
  sprintf(query, "SELECT `action`,`nick`,`msg`, FROM_UNIXTIME(`time`, '%%H:%%i:%%s') FROM `log` WHERE `cid` = %d", cid);
  dbquery(query);
  
  while((row = mysql_fetch_row(res))) tomirc(row[0], row[1], row[2], row[3], chan);
  
  fclose(log);
}

void tomirc(char *action, char *nick, char *msg, char *time, char *chan) {
  char real_msg[500];
  char real_nick[NICKLEN];
  int i, j;

  fprintf(log, "[%s] ", time);

  if(strcmp(action, "PRIVMSG") == 0) {
    if(msg[0] == '\x1') {
      strncpy(real_msg, "", 500);

      i = 8;
      j = 0;
      while(msg[i] != '\0') { 
	real_msg[j] = msg[i];
	++i;
	++j;
      }
      
      fprintf(log, "* %s %s\n", nick, real_msg);
    } else fprintf(log, "<%s> %s\n", nick, msg);
  } else if(strcmp(action, "MODE") == 0) fprintf(log, "*** %s sets mode: %s\n", nick, msg);
  else if(strcmp(action, "JOIN") == 0) fprintf(log, "*** %s has joined %s\n", nick, chan);
  else if(strcmp(action, "KICK") == 0) {
    strncpy(real_msg, "", 500);
    strncpy(real_nick, "", NICKLEN);

    i = 0;
    j = 0;

    while(msg[i] != '\0' && msg[i] != ' ') { 
      real_nick[j] = msg[i];
      ++i;
      ++j;
    }

    if(msg[i] == ' ') {
      ++i;
      j = 0;
      while(msg[i] != '\0') { 
	real_msg[j] = msg[i];
	++i;
	++j;
      }
    }
    fprintf(log, "*** %s was kicked by %s (%s)\n", real_nick, nick, real_msg);
  } else if(strcmp(action, "PART") == 0) fprintf(log, "*** %s has left %s\n", nick, chan);
  else if(strcmp(action, "TOPIC") == 0) fprintf(log, "*** %s changes topic to '%s'\n", nick, msg);
}
