#include <ctype.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <dirent.h>
#include "globals.h"
#include "utils.h"

/*
Zwraca status w odpowiedniej postaci dla jabbera
*/

int jbr_status(char *rstatus, int sizeofrstatus, int graph, int xemot, int icgi)
{
    int s = 0;
    char poms[300];

    if (strcmp(rstatus, "online") == 0)
	s = 0;
    if (strcmp(rstatus, "dnd") == 0)
	s = 1;
    if (strcmp(rstatus, "chat") == 0)
	s = 2;
    if (strcmp(rstatus, "offline") == 0)
	s = 3;
    if (strcmp(rstatus, "away") == 0)
	s = 4;
    if (strcmp(rstatus, "xa") == 0)
	s = 5;

    if (graph == 0) {
	snprintf(poms, sizeof(poms), "%s ", (s == 0) ? "onl" : (s == 1) ? "dnd" : (s == 2) ? "cht" : (s == 3) ? "off" : (s == 4) ? "awa" : "xaw");
    }
    else {
	snprintf(poms, sizeof(poms), "<img src=\"%s%s%s\" alt=\"%s\"/>",
		 (icgi) ? "/rtg/" : "?", (s == 0) ? "jonl" : (s == 1) ? "jdnd" : (s == 2) ? "jcht" : (s == 3)
		 ? "joff" : (s == 4) ? "jawa" : "jxaw",
		 (xemot) ? ".gif" : ".wbmp", (s == 0) ? "onl" : (s == 1) ? "dnd" : (s == 2) ? "cht" : (s == 3) ? "off" : (s == 4) ? "awa" : "xaw");
    }

    snprintf(rstatus, sizeofrstatus - 1, "%s", poms);
    return 0;
}

int gettnickr(char *uin, char *tnick, long int sizeoftnick)
{
    char linia[201], *nick, *end;
    FILE *wap;

    memset(tnick, sizeoftnick, 0);
    if ((wap = vfopen("r", "%.100s/wap-roster", home))) {
	while (fgets(linia, 200, wap)) {
	    nick = (char *) index(linia, ';');
	    if (nick) {
		nick++[0] = 0;
		end = (char *) index(nick, ';');
		if (end) {
		    end[0] = 0;
		    if (strcmp(uin, linia) == 0) {
			snprintf(tnick, sizeoftnick, "%s", nick);
			fclose(wap);
			return 0;
		    }
		}
	    }
	}
	//not found
	fclose(wap);
    }
    return 0;
}

int gettnick(char *uin, char *tnick, long int sizeoftnick)
{
    char linia[201], *n, *m, *n1;
    FILE *wap;

    if ((wap = vfopen("r", "%.100s/userlist", home))) {
	while (fgets(linia, 200, wap)) {
	    n = (char *) index(linia, ';');
	    if (n)
		n = (char *) index(n + 1, ';');
	    if (n)
		n = (char *) index(n + 1, ';');
	    if (n) {
		// w n+1 jest nick
		m = (char *) index(n + 1, ';');
		if (m)
		    m++[0] = 0;
		if (m)
		    m = (char *) index(m, ';');
		if (m)
		    m = (char *) index(m + 1, ';');

		n1 = (char *) index(m + 1, ';');
		if (n1 != NULL)
		    n1[0] = 0;
		n1 = (char *) index(m + 1, 10);
		if (n1 != NULL)
		    n1[0] = 0;
		n1 = (char *) index(m + 1, 13);
		if (n1 != NULL)
		    n1[0] = 0;

		if (m + 1) {
		    if (strcmp(uin, m + 1) == 0) {
			snprintf(tnick, sizeoftnick, "%s", n + 1);
			fclose(wap);
			return 0;
		    }
		}
	    }
	}
	//not found
	fclose(wap);
    }
    return 0;
}

int gettuin(char *nick, char *targetuin, long int sizeoftargetuin)
{
    char linia[201], *n, *m;
    FILE *wap;

    if ((wap = vfopen("r", "%.100s/userlist", home))) {
	while (fgets(linia, 200, wap)) {
	    n = (char *) index(linia, ';');
	    if (n)
		n = (char *) index(n + 1, ';');
	    if (n)
		n = (char *) index(n + 1, ';');
	    if (n) {
		if (strncmp(n + 1, nick, strlen(nick)) == 0) {
		    // znaleziono!
		    fclose(wap);

		    m = (char *) index(n + 1, ';');
		    if (m)
			m = (char *) index(m + 1, ';');
		    if (m)
			m = (char *) index(m + 1, ';');

		    n = (char *) index(linia, 10);
		    if (n != NULL)
			n[0] = 0;
		    n = (char *) index(linia, 13);
		    if (n != NULL)
			n[0] = 0;

		    if (m) {
			snprintf(targetuin, sizeoftargetuin, "%ld", atol(m + 1));
		    }
		    return 0;
		}
	    }
	}
	//not found
	fclose(wap);
    }
    return 0;
}


/*
licznik bajtow nadanych i wyslanych z rtg z podzialem
na sesje freeblwr
*/

int countersadd(char *pathhome, long int in, long int out)
{
    char pom[255], ins[42], outs[42];
    FILE *plik;

    snprintf(ins, sizeof(ins), "0");
    snprintf(outs, sizeof(outs), "0");
    if (debug > 1)
	printf("[rtg] %s in %ld out %ld\n", pathhome, in, out);
    snprintf(pom, sizeof(pom), "%s/wap-counters", pathhome);
    if ((plik = fopen(pom, "r"))) {
	if (!feof(plik))
	    fgets(ins, 41, plik);
	if (!feof(plik))
	    fgets(outs, 41, plik);
	fclose(plik);
    }
    if ((plik = fopen(pom, "w"))) {
	fprintf(plik, "%ld\n%ld\n", atol(ins) + in, atol(outs) + out);
	fclose(plik);
    }
    return 0;
}

/*
funkcja czyści katalog slotu o podanym numerze
gdy kat==1 kasuje również sam katalog
*/

int clrdir(int slot, int kat)
{
    struct dirent **namelist;
    char wapfile[201], tmp[201];
    int n, k;

    //wyczysc katalog
    snprintf(tmp, sizeof(tmp), "%s/%d/", home, slot);
    n = scandir(tmp, &namelist, 0, alphasort);
    if (n < 0) {
	// jakis problem z lista katalogow
	if (debug > 0)
	    printf("[%d] Problem z katalogiem: %s\n", slot, tmp);
	return 0;
    }
    else {
	k = n;
	while (n--) {
	    snprintf(wapfile, sizeof(wapfile), "%s%s", tmp, namelist[k - n - 1]->d_name);
	    unlink(wapfile);
	}
	free(namelist[k - n - 1]);
    }
    free(namelist);

    if (kat == 1) {
	snprintf(tmp, sizeof(tmp), "%s/%d/", home, slot);
	rmdir(tmp);
    }

    return 0;
}

/*
funkcja szuka wolnego slotu dla freeblwr mode
jeśli go znajdzie zwraca jego numer, jeśli go nie znajdzie
zwraca zero
*/

int findslot(int maxslots)
{
    int i, fs = 0;
    char tmp[201];
    struct stat buf;
    time_t tczas;
    long int czas = 0;

    time(&tczas);

//szukam wogole wolnego slotu
    for (i = 1; i <= maxslots; i++) {
	snprintf(tmp, sizeof(tmp), "%.150s/%d", home, i);
	if (mkdir(tmp, 0700) == 0) {	// znaleziono slot
	    if (debug > 0)
		printf("[search] Znaleziono wolny slot %d\n", i);
	    return i;
	}
    }

//szukam najstarszego slotu
    if (debug > 0)
	printf("[search] Brak wolnych slotow szukam najstarszego\n");
    for (i = 1; i <= maxslots; i++) {
	snprintf(tmp, sizeof(tmp), "%.150s/%d/wap-query.log", home, i);
	if (lstat(tmp, &buf) == 0) {
	    if (buf.st_mtime < czas || czas == 0) {
		czas = buf.st_mtime;
		fs = i;
	    }
	}
    }
    if (debug > 0)
	printf("[search] Najstarszy slot %d\n", fs);

    if (fs == 0)
	return 0;

// jeśli najstarsze gniazdo było urzywane w ciągu 10 minut to
// go nie można urzywać

    if ((tczas - czas) < 600) {
	if (debug > 0)
	    printf("[search] Slot %d nadal urzywany\n", fs);
	return 0;
    }

//jesli bardzo stary
    snprintf(tmp, sizeof(tmp), "%.150s/%d/wap-query.log", home, fs);
    if (unlink(tmp) == 0) {
	FILE *pwap;

	//tylko 1 proces tu wejdzie jesli szukalo wiecej (jeden zdarzy odlinkowac plik)
	//mozna by poszukac jeszcze, ale nie ma wogole wolnych
	//a jeszcze 2 naraz sie dobija

	//zatrzymaj ekg

	if (debug > 0)
	    printf("[search] slot %d przedawniony\n", fs);
	snprintf(tmp, sizeof(tmp), "%.150s/%d/pipewap", home, fs);
	if ((pwap = fopen(tmp, "r+"))) {
	    //znaczy sie dziala
	    fprintf(pwap, "/quit\n");
	    fclose(pwap);
	    sleep(2);		//daj mu czas na zamkniecie
	}

	clrdir(fs, 0);

	return fs;
    }				//udal sie unlink

//sorry, no free slots
    return 0;
}

/*
Funkcja pisze w rurke do ekg
zwraca 0 gdy się nie udało otworzyc rurki lub 1 gdy się udało
*/

int doekg(const char *a, ...)
{
    va_list ap;
    FILE *wap;

    if ((wap = vfopen("r+", "%s/pipewap", home))) {
	va_start(ap, a);
	vfprintf(wap, a, ap);
	va_end(ap);
	fclose(wap);
	return 1;
    }
    return 0;
}

/*
Funkcja pisze w rurke do jabbera
zwraca 0 gdy się nie udało otworzyc rurki lub 1 gdy się udało
*/

int dojbr(const char *a, ...)
{
    va_list ap;
    FILE *wap;

    if ((wap = vfopen("r+", "%s/pipewapj", home))) {
	va_start(ap, a);
	vfprintf(wap, a, ap);
	va_end(ap);
	fclose(wap);
	return 1;
    }
    return 0;
}

/*
Funkcja pisze w rurke do irssi
zwraca 0 gdy się nie udało otworzyc rurki lub 1 gdy się udało
*/

int doirssi(const char *a, ...)
{
    va_list ap;
    FILE *wap;

    if ((wap = vfopen("r+", "%s/.irssi/rtg", (char *) getenv("HOME")))) {
	va_start(ap, a);
	vfprintf(wap, a, ap);
	va_end(ap);
	fclose(wap);
	return 1;
    }
    return 0;
}

int notalphasort(const void *a, const void *b)
{
    return alphasort(b, a);
}

FILE *vfopen(const char *mode, const char *path, ...)
{
    char plik[256];
    va_list ap;

    va_start(ap, path);
    vsnprintf(plik, sizeof(plik), path, ap);
    va_end(ap);
    return fopen(plik, mode);
}

/*
Funkcja pisze do logu
*/

int dologu(int noold, const char *a, ...)
{
    va_list ap;
    FILE *wap;

    if (noold == 1)
	return 0;

    if ((wap = vfopen("a", "%.100s/wap-query.log", home))) {
	va_start(ap, a);
	vfprintf(wap, a, ap);
	va_end(ap);
	fclose(wap);
    }
    return 0;
}
