#include "inf71320_SMS.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "inf71320_usersgroups.h"
#include "inf71320_keyboard.h"


int main( int argc, char *argv[] )
{
	int mainqueue;
	Request req;
	Ack reqack;
	
	if ( argc != 2 )
	{
		printf( "Zla ilosc parametrow\n" );
		return 1;
	}
	if ( read_server_conf( argv[1] ) != 0 )
	{
		printf( "Brak pliku konfiguracyjnego lub bledna struktura\n" );
		delete_usersgroups();
		return 1;
	}
	printf( "SMS Server by Krzysztof Kotarski is running...\n" );
	printf( "Dodaje grupy:\n" );
	write_groups();
	printf( "Dodaje uzytkownikow:\n" );
	write_users();
	//printf( "\n" );
	mainqueue = msgget( SRVR_MSG_Q, IPC_CREAT | 0666 );
	init_keyboard();
	while ( !kbhit() )
	{
		close_keyboard();
		
		int stat;
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_LOGIN, IPC_NOWAIT ) > 0 )
		{//login
			if ( ( stat = log_in(req) ) == 0 )
			{
				reqack.m_type = M_ACK_LOGIN;
				reqack.result = RESULT_OK;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s zalogowal sie poprawnie\n", req.login );
			}	
			else
			{
				if( stat == 2 )
				{
					reqack.m_type = M_ACK_LOGIN;
					reqack.result = RESULT_ERROR;
					strcpy(reqack.msg,"Przekroczona dopuszczalna ilosc prob logowania");
					msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
					printf( ">>Proba logowania uzytkownika %s nie powiodla sie\n", req.login );
					printf( ">>Przekroczona dopuszczalna ilosc prob logowania\n" );
				}
				else
				{
					reqack.m_type = M_ACK_LOGIN;
					reqack.result = RESULT_ERROR;
					strcpy(reqack.msg,"");
					msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
					printf( ">>Proba logowania uzytkownika %s nie powiodla sie\n", req.login );
				}
			}
		}
		
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_LOGOUT, IPC_NOWAIT ) > 0 )
		{//logout
			if ( log_out(req) == 0 )
			{
				reqack.m_type = M_ACK_LOGOUT;
				reqack.result = RESULT_OK;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s wylogowal sie poprawnie\n", req.login );
			}	
			else
			{
				reqack.m_type = M_ACK_LOGOUT;
				reqack.result = RESULT_ERROR;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Proba wylogowania uzytkownika %s nie powiodla sie\n", req.login );
			}
		}
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_PASSWD, IPC_NOWAIT ) > 0 )
		{//change password
			if ( change_password(req) == 0 )
			{
				reqack.m_type = M_ACK_PASSWD;
				reqack.result = RESULT_OK;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Haslo uzytkownika %s zostalo zmienione\n", req.login );
			}	
			else
			{
				reqack.m_type = M_ACK_PASSWD;
				reqack.result = RESULT_ERROR;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Proba zmiany hasla uzytkownika %s nie powiodla sie\n", req.login );
			}
		}
		
		
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_VIEWALL, IPC_NOWAIT ) > 0 )
		{//show all users
			if ( show_all_users(req,&reqack) == 0 )
			{
				reqack.m_type = M_ACK_VIEWALL;
				reqack.result = RESULT_OK;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s otrzymal liste wszytskich uzytkownikow\n", req.login );
			}	
			else
			{
				reqack.m_type = M_ACK_VIEWALL;
				reqack.result = RESULT_ERROR;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s nie otrzymal listy wszytskich uzytkownikow\n", req.login );
			}
		}
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_VIEWLOG, IPC_NOWAIT ) > 0 )
		{//show logged users
			if ( show_logged_users(req,&reqack) == 0 )
			{
				reqack.m_type = M_ACK_VIEWLOG;
				reqack.result = RESULT_OK;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s otrzymal liste wszytskich uzytkownikow\n", req.login );
			}	
			else
			{
				reqack.m_type = M_ACK_VIEWLOG;
				reqack.result = RESULT_ERROR;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s nie otrzymal listy wszytskich uzytkownikow\n", req.login );
			}
		}
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_VIEWGRP, IPC_NOWAIT ) > 0 )
		{//show group member users
			if ( show_group_member_users(req,&reqack) == 0 )
			{
				reqack.m_type = M_ACK_VIEWGRP;
				reqack.result = RESULT_OK;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s otrzymal liste uzytkownikow z grupy %s\n", req.login, req.data );
			}	
			else
			{
				reqack.m_type = M_ACK_VIEWGRP;
				reqack.result = RESULT_ERROR;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s nie otrzymal listy uzytkownikow z grupy %s\n", req.login, req.data );
			}
		}
		
		
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_SUBSCR, IPC_NOWAIT ) > 0 )
		{//add user to group
			if ( add_user_to_group(req) == 0 )
			{
				reqack.m_type = M_ACK_SUBSCR;
				reqack.result = RESULT_OK;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s zostal dodany do grupy %s\n", req.login, req.data );
			}	
			else
			{
				reqack.m_type = M_ACK_SUBSCR;
				reqack.result = RESULT_ERROR;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s nie zostal dodany do grupy %s\n", req.login, req.data );
			}
		}
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_UNSUBSCR, IPC_NOWAIT ) > 0 )
		{//remove user from group
			if ( remove_user_from_group(req) == 0 )
			{
				reqack.m_type = M_ACK_UNSUBSCR;
				reqack.result = RESULT_OK;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s zostal usuniety z grupy %s\n", req.login, req.data );
			}	
			else
			{
				reqack.m_type = M_ACK_UNSUBSCR;
				reqack.result = RESULT_ERROR;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s nie zostal usuniety z grupy %s\n", req.login, req.data );
			}
		}
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_GETGRPS, IPC_NOWAIT ) > 0 )
		{//show all groups
			if ( show_all_groups(req,&reqack) == 0 )
			{
				reqack.m_type = M_ACK_GETGRPS;
				reqack.result = RESULT_OK;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s otrzymal liste wszytskich grup\n", req.login );
			}	
			else
			{
				reqack.m_type = M_ACK_GETGRPS;
				reqack.result = RESULT_ERROR;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Uzytkownik %s nie otrzymal listy wszytskich grup\n", req.login );
			}
		}
		
		
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_SNDUSR, IPC_NOWAIT ) > 0 )
		{//send message to user
			if ( send_to_user(req, &reqack) == 0 )
			{
				reqack.m_type = M_ACK_SNDUSR;
				reqack.result = RESULT_OK;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Wiadomosc od uzytkownika %s do uzytkownika %s zostala wyslana\n", req.login, req.data );
			}	
			else
			{
				reqack.m_type = M_ACK_SNDUSR;
				reqack.result = RESULT_ERROR;
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Wiadomosc od uzytkownika %s do uzytkownika %s nie zostala wyslana\n", req.login, req.data );
			}
		}
		if ( msgrcv( mainqueue, &req, sizeof( req ) - sizeof( req.m_type ), M_REQ_SNDGRP, IPC_NOWAIT ) > 0 )
		{//send message to group
			if ( send_to_group(req) == 0 )
			{
				reqack.m_type = M_ACK_SNDGRP;
				reqack.result = RESULT_OK;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Wiadomosc od uzytkownika %s do grupy %s zostala wyslana\n", req.login, req.data );
			}	
			else
			{
				reqack.m_type = M_ACK_SNDUSR;
				reqack.result = RESULT_ERROR;
				strcpy(reqack.msg,"");
				msgsnd( get_user_queue( req.login ), &reqack, sizeof( reqack ) - sizeof( reqack.m_type ), 0 );
				printf( ">>Wiadomosc od uzytkownika %s do grupy %s nie zostala wyslana\n", req.login, req.data );
			}
		}
		usleep(1);
		init_keyboard();
	}
	close_keyboard();
	close_queues();
	msgctl( mainqueue, IPC_RMID, 0 );
	return 0;
}

