#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include "thread.h"
#include "server.h"
#include "worker.h"
#include "foscreen.h"
#include "socket.h"
#include "client.h"
#include "webrequest.h"
#include "log.h"

using namespace NT;

FoWebServer server;

FOHANDLE worker_started_event = NULL;
FOHANDLE worker_finished_event = NULL;
FOHANDLE webserver_started_event = NULL;
FOHANDLE webserver_finished_event = NULL;
FOHANDLE global_quit_event = NULL;

/* TODO
 *
 * - [*] minimal ncurses
 * - [*] maga a webserver (accept loop)
 * - [*] global threading
 * - [*] http request parser (get/post)
 * - [ ] output generator (http header)
 * - [ ] mime encoder
 * - [ ] json encoder :)
 */

void worker_thread( LPVOID params ) {
	FoWorkerThread worker;
	worker.Init();
	FoSetEvent( worker_started_event );
	worker.Do( global_quit_event );
	worker.Deinit();
	FoSetEvent( worker_finished_event );
}

void webserver_thread( LPVOID params ) {
	server.Init();
	FoSetEvent( webserver_started_event );
	server.Do( global_quit_event );
	server.Deinit();
	FoSetEvent( webserver_finished_event );
}

void signal_handler( int signum ) {
	switch (signum) {
	case SIGINT:
	case SIGKILL:
	case SIGQUIT:
	case SIGTERM:
		LogMessage( "signal got" );
		FoSetEvent( global_quit_event );
		server.Stop();
		break;
	}
}

void init_signals() {
	signal( SIGINT , signal_handler );
	signal( SIGKILL , signal_handler );
	signal( SIGQUIT , signal_handler );
	signal( SIGTERM , signal_handler );
}

int main( int argc, char *args[]) {
	DWORD threadid;

	global_quit_event = FoCreateEvent( NULL , true , false , NULL );
	// initialize signals
	init_signals();

	// starting workerthread	
	worker_started_event = FoCreateEvent( NULL , true , false , NULL );
	worker_finished_event = FoCreateEvent( NULL , true , false , NULL );
	FOHANDLE worker_thread_handle = FoCreateThread( NULL , 0 , (LPTHREAD_START_ROUTINE) worker_thread , NULL , 0 , &threadid );
	FoCloseHandle( worker_thread_handle );
	FoWaitForSingleObject( worker_started_event , INFINITE );
	FoCloseHandle( worker_started_event );worker_started_event = NULL;

	// starting webserverthread
	webserver_started_event = FoCreateEvent( NULL , true , false , NULL );
	webserver_finished_event = FoCreateEvent( NULL , true , false , NULL );
	FOHANDLE webserver_thread_handle = FoCreateThread( NULL , 0 , (LPTHREAD_START_ROUTINE) webserver_thread , NULL , 0 , &threadid );
	FoCloseHandle( webserver_thread_handle );
	FoWaitForSingleObject( webserver_started_event , INFINITE );
	FoCloseHandle( webserver_started_event );webserver_started_event = NULL;

	// FoScreen *screen = new FoScreen();
	// NTSetGlobalScreen( screen );

	while (FoWaitForSingleObject( global_quit_event , 0 )!=WAIT_OBJECT_0) {
		// screen->RefreshScreen();
		usleep( 100000 );
	}


	// shutdown
	// -- waiting shutdown worker
	FoWaitForSingleObject( worker_finished_event , INFINITE );
	FoCloseHandle( worker_finished_event ); worker_finished_event = NULL;

	// -- waiting webserver shutdown
	FoWaitForSingleObject( webserver_finished_event , INFINITE );
	FoCloseHandle( webserver_finished_event ); webserver_finished_event = NULL;

	FoCloseHandle( global_quit_event );global_quit_event = NULL;

	// delete screen;screen = NULL; 
	return 0;
}
