/*
 * Soubor:  iri.c
 * Datum:   06.08.2012
 * Autor:   Stanislav Bárta, xbarta29@stud.fit.vutbr.cz
 * Projekt: IM modul
 * Popis:   soubor obsahujici funkce k vytvoreni a odeslani zprav IRI
 */

#include "iri.h"

char *text_kanal = "\"IRC CHANNEL\"";

char *PROTOKOL[] = {
	"\"XMPP\"",
	"\"IRC\"",
	"\"OSCAR\"",
	"\"YMSG\""
};

char *TRANSPORTNI_PROTOKOL[] = {
	"", // neuvedeno
	"\"TCP\"",
	"\"UDP\""
};

char *TYP_IRI[] = {
	"\"REPORT\"",
	"\"BEGIN\"",
	"\"CONTINUE\"",
	"\"END\""
};

char *TYP_ID[] = {
	"\"XMPP LOGIN\"",
	"\"IRC LOGIN\"",
	"\"OSCAR LOGIN\"",
	"\"YMSG LOGIN\""
};

char *TYP_UDALOSTI_STR[] = {
	"authenticated",
	"logged in",
	"message received",
	"message sent",
	"notification received",
	"notification sent",
	"logged out",
	"status changed to online",
	"status changed to away",
	"status changed to chat",
	"status changed to DND",
	"status changed to N/A",
	"status changed to occupied",
	"status changed to invisible",
	"status changed to available",
	"status changed to BRB",
	"status changed to busy",
	"status changed to notathome",
	"status changed to notatdesk",
	"status changed to notinoffice",
	"status changed to onphone",
	"status changed to onvacation",
	"status changed to outtolunch",
	"status changed to steppedout",
	"status changed to custom",
	"status changed to evil",
	"status changed to depression",
	"status changed to athome",
	"status changed to atwork",
	"status changed to lunch",
	"connected to channel",
	"disconnected from channel",
	"connected to server",
	"initiated encrypted communication",
	"encrypted communication in progress"
};

char *USPECH_AKCE_STR[] = {
	"unknown",
	"successfully",
	"unsuccessfully"
};

/*
 * otevre TCP spojeni s MF ktere se budou zasilat vytvorene zpravy IRI
 */
int otevri_spojeni_pro_iri(void)
{
	int len;
	struct sockaddr_un remote;
	if ((socket_iri = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
	{
		return 1;
	}
	
	remote.sun_family = AF_UNIX;
	strcpy(remote.sun_path, "/tmp/iricol");
	len = strlen(remote.sun_path) + sizeof(remote.sun_family);
	if (connect(socket_iri, (struct sockaddr *)&remote, len) == -1)
	{
		perror("Chyba pri pripojovani k socketu");
		return 1;
	}
	
	return 0;
}

/*
 * uzavreni spojeni s MF pri ukonceni programu
 */
void uzavri_spojeni_pro_iri(void)
{
	close(socket_iri);
}

/*
 * podle zadanych parametru je vytvorena IRI v textovem formatu a je vracen ukazatel na tento retezec
 */
char *vytvor_iri(int typ_iri, int protokol, struct sezeni *Sezeni, int typ_udalosti, int uspech_udalosti, struct timeval *cas, char *kanal, char *odesilatel, char *prijemce, char *service)
{
	char *oddelovac = ", ";

	char port_str[20];
	sprintf(port_str, "%d", Sezeni->port);
	char port_2_str[20];
	sprintf(port_2_str, "%d", Sezeni->port_2);

	char adresa_str[INET6_ADDRSTRLEN];
	char adresa_2_str[INET6_ADDRSTRLEN];
	if(Sezeni->typ_ip == IPverze4)
	{
		inet_ntop(AF_INET, &(Sezeni->ipv4_adresa), adresa_str, INET6_ADDRSTRLEN);
		inet_ntop(AF_INET, &(Sezeni->ipv4_adresa_2), adresa_2_str, INET6_ADDRSTRLEN);
	}
	else if(Sezeni->typ_ip == IPverze6)
	{
		inet_ntop(AF_INET6, &(Sezeni->ipv6_adresa), adresa_str, INET6_ADDRSTRLEN);
		inet_ntop(AF_INET6, &(Sezeni->ipv6_adresa_2), adresa_2_str, INET6_ADDRSTRLEN);
	}

	char timestamp[60];
	sprintf(timestamp, "%ld.%ld", (long int)cas->tv_sec, (long int)cas->tv_usec);

	
	// vypocet velikosti vytvarene iri
	int velikost_zpravy = 0;
	velikost_zpravy += strlen(PROTOKOL[protokol]);
	velikost_zpravy += strlen(timestamp);
	velikost_zpravy += strlen(TYP_IRI[typ_iri]);
	velikost_zpravy += strlen(TYP_UDALOSTI_STR[typ_udalosti]);
	velikost_zpravy += strlen(USPECH_AKCE_STR[uspech_udalosti]);
	velikost_zpravy += 6; // pro from nebo to u komunikace na aplikacni vrstve

	// vychozi velikosti zavorek, oddelovacu a uvozovek
	velikost_zpravy += 10; // uvozovky
	velikost_zpravy += 10; // zavorky
	velikost_zpravy += 12*strlen(oddelovac);
	velikost_zpravy += 1; // pro spojeni uzivatele a serveru znakem @ u protokolu irc
	

	// ip adresy a porty jsou vzdy uvadeny
	velikost_zpravy += strlen(TRANSPORTNI_PROTOKOL[Sezeni->transportni_protokol]);
	velikost_zpravy += strlen(adresa_str);
	velikost_zpravy += strlen(port_str);
	velikost_zpravy += strlen(adresa_2_str);
	velikost_zpravy += strlen(port_2_str);

	// koncove znaky
	velikost_zpravy += 2;

	// rezerva pro pripad chyby ve vypoctu TODO po overeni spravnosti vypoctu nebude potreba
	velikost_zpravy += 10;
	
	if(Sezeni->ID_uzivatele != NULL)
	{
		velikost_zpravy += strlen(Sezeni->ID_uzivatele);
	}
	if(Sezeni->server != NULL)
	{
		velikost_zpravy += strlen(Sezeni->server);
	}

	if(odesilatel != NULL)
	{
		velikost_zpravy += strlen(odesilatel); 
	}

	if(prijemce != NULL)
	{
		velikost_zpravy += strlen(prijemce);
	}

	if(kanal != NULL)
	{
		velikost_zpravy += strlen(text_kanal);
		velikost_zpravy += strlen(kanal);
	}

	if(service != NULL)
	{
		velikost_zpravy += strlen(service);
	}

	// vkladani obsahu do vytvoreneho prostoru pro iri
	char *vysledne_iri = NULL;
	vysledne_iri = (char *) malloc(velikost_zpravy*sizeof(char));

	strcpy(vysledne_iri, PROTOKOL[protokol]);
	vysledne_iri = strcat(vysledne_iri, oddelovac);
	vysledne_iri = strcat(vysledne_iri, timestamp);
	vysledne_iri = strcat(vysledne_iri, oddelovac);
	vysledne_iri = strcat(vysledne_iri, TYP_IRI[typ_iri]);
	vysledne_iri = strcat(vysledne_iri, oddelovac);
	vysledne_iri = strcat(vysledne_iri, "\"");
	vysledne_iri = strcat(vysledne_iri, TYP_UDALOSTI_STR[typ_udalosti]);
	if((typ_udalosti == TYP_PRIJATA_ZPRAVA || typ_udalosti == TYP_PRIJATO_OZNAMENI) && (odesilatel != NULL || service != NULL))
	{
		vysledne_iri = strcat(vysledne_iri, " from ");
		if(odesilatel != NULL)
		{
			vysledne_iri = strcat(vysledne_iri, odesilatel);
		}
		else
		{
			vysledne_iri = strcat(vysledne_iri, service);
		}
	}
	else if((typ_udalosti == TYP_ODESLANA_ZPRAVA || typ_udalosti == TYP_ODESLANO_OZNAMENI) && (prijemce != NULL || service != NULL))
	{
		vysledne_iri = strcat(vysledne_iri, " to ");
		if(prijemce != NULL)
		{
			vysledne_iri = strcat(vysledne_iri, prijemce);
		}
		else
		{
			vysledne_iri = strcat(vysledne_iri, service);
		}
	}
	vysledne_iri = strcat(vysledne_iri, " ");
	vysledne_iri = strcat(vysledne_iri, USPECH_AKCE_STR[uspech_udalosti]);
	vysledne_iri = strcat(vysledne_iri, "\"");
	vysledne_iri = strcat(vysledne_iri, oddelovac);
	vysledne_iri = strcat(vysledne_iri, "[");

	if(Sezeni->ID_uzivatele != NULL && !(typ_udalosti == TYP_PRIJATA_ZPRAVA || typ_udalosti == TYP_PRIJATO_OZNAMENI || typ_udalosti == TYP_ODESLANA_ZPRAVA || typ_udalosti == TYP_ODESLANO_OZNAMENI))
	{
		vysledne_iri = strcat(vysledne_iri, "(");
		vysledne_iri = strcat(vysledne_iri, TYP_ID[protokol]);
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, Sezeni->ID_uzivatele);
		if(Sezeni->server != NULL)
		{
			vysledne_iri = strcat(vysledne_iri, "@");
			vysledne_iri = strcat(vysledne_iri, Sezeni->server);
		}
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, ")");
		vysledne_iri = strcat(vysledne_iri, oddelovac);
	}

	if(Sezeni->ID_uzivatele != NULL && (typ_udalosti == TYP_PRIJATA_ZPRAVA || typ_udalosti == TYP_PRIJATO_OZNAMENI))
	{
		vysledne_iri = strcat(vysledne_iri, "(");
		vysledne_iri = strcat(vysledne_iri, TYP_ID[protokol]);
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, Sezeni->ID_uzivatele);
		if(Sezeni->server != NULL)
		{
			vysledne_iri = strcat(vysledne_iri, "@");
			vysledne_iri = strcat(vysledne_iri, Sezeni->server);
		}
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, ")");
		vysledne_iri = strcat(vysledne_iri, oddelovac);
	}

	if(Sezeni->ID_uzivatele != NULL && (typ_udalosti == TYP_ODESLANA_ZPRAVA || typ_udalosti == TYP_ODESLANO_OZNAMENI))
	{
		vysledne_iri = strcat(vysledne_iri, "(");
		vysledne_iri = strcat(vysledne_iri, TYP_ID[protokol]);
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, Sezeni->ID_uzivatele);
		if(Sezeni->server != NULL)
		{
			vysledne_iri = strcat(vysledne_iri, "@");
			vysledne_iri = strcat(vysledne_iri, Sezeni->server);
		}
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, ")");
		vysledne_iri = strcat(vysledne_iri, oddelovac);
	}

	if(typ_udalosti == TYP_PRIPOJENI_KE_KANALU || typ_udalosti == TYP_ODPOJEN_OD_KANALU)
	{
		vysledne_iri = strcat(vysledne_iri, "(");
		vysledne_iri = strcat(vysledne_iri, text_kanal);
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, kanal);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, ")");
	}

	if(!(typ_udalosti == TYP_PRIPOJENI_KE_KANALU || typ_udalosti == TYP_ODPOJEN_OD_KANALU))
	{
		vysledne_iri = strcat(vysledne_iri, "(");
		vysledne_iri = strcat(vysledne_iri, TRANSPORTNI_PROTOKOL[Sezeni->transportni_protokol]);
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, "(");
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, adresa_str);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, port_str);
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, adresa_2_str);
		vysledne_iri = strcat(vysledne_iri, "\"");
		vysledne_iri = strcat(vysledne_iri, oddelovac);
		vysledne_iri = strcat(vysledne_iri, port_2_str);
		vysledne_iri = strcat(vysledne_iri, "))");
	}
	vysledne_iri = strcat(vysledne_iri, "]");
	vysledne_iri = strcat(vysledne_iri, "\n\0");

	return vysledne_iri;
}

/*
 * zasle vytvorenou IRI do MF pomoci drive vytvoreneho spojeni
 */
void odesli_iri(char *iri)
{
	send(socket_iri, iri, strlen(iri), 0);
}

