#include "common.h"
#include <signal.h>
#include "users.h"
#include "commandline.h"
#include "database.h"
#include "visualiser.h"

//#include "SDL.h"
//#include "SDL_Net.h"

#include "network.h"
#include "user_manager.h"

bool killsignal = FALSE;

// commandline command for status reporting of users, its in here so
// that i don't include any nest specific code in the commandline.
wxString status(CommandLine *cmdline,const wxString &args)
{
	wxString msg = "\r\nUsers...\r\n";
	
	for ( unsigned int i = 0; i < users->GetCount(); i++ )
    {
		UserData *user = &users->Item(i);
		msg += user->toString() << "\r\n";
    }
	msg += "\r\n";
	return msg;
}

wxString removeuser(CommandLine *cmdline,const wxString &args)
{
	wxString msg;
	UserData *tmp = users->Find(args);
	if (tmp)
	{
		if (tmp->prev!=NULL && tmp->prev!=tmp)
		{
			tmp->prev->next = tmp->next;
			tmp->next->prev = tmp->prev;

			UserManagement::UserEvent evt;
			evt.sEventType = "CONNECT";
			evt.data1 = tmp->prev;
			evt.data2 = tmp->next;
			UserManagement::UserManager::getManager()->QueueEvent(evt);
		}
		UserTable *table = new UserTable();
		if (!table->Open())
		{
			// An error occurred opening (setting up) the table
			wxLogError(wxT("Failed to open usertable for insertion of data!"));
			return "Database access failed.";
		}
		if (table->FetchByName(tmp->username))
		{
			table->isOnline = 0;
			table->Update();
			table->GetDb()->CommitTrans();
		}
		users->Remove(tmp);
		msg.Printf("%s removed.\r\n",args.c_str());
	}
	else
		msg.Printf("Error %s not found.\r\n",args.c_str());
	return msg;
}
// commandline command for status reporting of users, its in here so
// that i don't include any nest specific code in the commandline.
wxString userinfo(CommandLine *cmdline,const wxString &args)
{
	wxString msg;
	if (args.Length()==0)
	{
		for (unsigned int i=0; i < users->GetCount(); i++)
		{
			UserData *userp = &users->Item(i);
			wxString msg2;
			msg2.Printf("%s\t(%s) udp:%d tcp:%d\r\n",userp->username.c_str(),
					userp->ip.c_str(),userp->udp_port,userp->tcp_port);
			msg.Append(msg2);
		}
	}
	else
	{
		// find the user with the given arg name
		UserData *userp = users->Find(args);
		if (userp)
			msg.Printf("%s\t(%s) udp:%d tcp:%d\r\n",userp->username.c_str(),
					userp->ip.c_str(),userp->udp_port,userp->tcp_port);
	}
	return msg;
}

void signal_handler(int v)
{
	// do shutdown
	killsignal = TRUE;
}

bool handleCtrlSocket(Network::TCP_socket socket)
{
	CommandLine *cl = new CommandLine(socket);
	// register more commands
	cl->RegisterCmd(status,"status","Displays server status information.");
	cl->RegisterCmd(userinfo,"user","Displays information about the requested user");
	cl->RegisterCmd(removeuser,"kick","Kicks the given user from the server");
	cl->Run();
	return true;
}

int main(int argc, char *argv[])
{
	if ( !wxInitialize() )
	{
		fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
	}

	signal(SIGABRT,signal_handler);
	signal(SIGINT,signal_handler);

	wxLog::SetTimestamp(_T("%d/%m/%y %H:%M"));

	// wxWindows now initialised, we can start logging through it now.
	// start SDL
	wxLogMessage(_T("Starting SDL"));
	if(SDL_Init(0)==-1)
	{
		wxLogError(_T("Client: SDL_Init error : %s"), SDL_GetError());
		return FALSE;
	}

	// initialise SDL_net
	wxLogMessage(_T("Starting SDL_Net"));
	if(SDLNet_Init()==-1)
	{
		wxLogError(_T("Client: SDLNet_Init error : %s"), SDL_GetError());
		return FALSE;
	}

	// all libraries now initialised, begin process.
	// create list to store users in
	users = new UsersList();

	// make db connection
	if (!Database::SetupDatabase())
		wxLogError(_T("Database connection failed...."));

	// start login manager to govern connections
	UserManagement::UserManager *manager = UserManagement::UserManager::getManager();
	manager->Run();

	// start visualiser to begin making maps
	Visualiser *vis = new Visualiser(30000);
	vis->Run();

	// create a listening TCP socket on port 2000 (server)
	Network::StartServer(killsignal,CTRL_PORT,handleCtrlSocket);
	
	wxLogMessage(_T("Server: going down...."));

	// ---- SHUTDOWN ---- begin shutdown....
	delete users;
	// quit SDL_net
	SDLNet_Quit();
	// quit SDL
	SDL_Quit();
	wxUninitialize();

	return 0;
}

