#ifdef WIN32
#include <main.h>
#else
#include <spawn.h>
#endif
#include <Zeit.h>
#include <iostream>
#include <fstream>
#include <Text.h>
#include <Datei.h>
#include <InitDatei.h>
#include <sql.h>
#include <Klient.h>

using namespace Framework;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result" 
#ifdef WIN32
int KSGStart Framework::Start( Startparam p )
#else
int main()
#endif
{
#ifdef _DEBUG
	chdir( "/test/startup" );
#else
	chdir( "/ksg/Server/startup" );
#endif
	Network::Start( 100 );
	Zeit *z = getZeit();
	Text *pfad = new Text( "../log/startup/" );
	pfad->append( z->getZeit( "y-m-d_h-i-s.log" ) );
	z->release();
	DateiPfadErstellen( pfad->getThis() );
	std::ofstream file;
	file.open( pfad->getText() );
	std::streambuf* sbuf = std::cout.rdbuf();
	std::cout.rdbuf( file.rdbuf() );
	pfad->release();
    system( "/usr/lib/sendmail -t < mail" );
	std::cout << "Startet...\n";
	std::cout << "Lese init Datei ../data/startup.ini ...\n";
	InitDatei *dat = new InitDatei( "../data/startup.ini" );
	if( !dat->laden() )
	{
		std::cout << "error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 1;
	}

	std::cout << "Verbindung mit Datenbank wird hergestellt...\n";
	if( !dat->wertExistiert( "DBIP" ) )
	{
		std::cout << "error: Kein 'DBIP' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	if( !dat->wertExistiert( "DBPort" ) )
	{
		std::cout << "error: Kein 'DBPort' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	if( !dat->wertExistiert( "DBBenutzer" ) )
	{
		std::cout << "error: Kein 'DBBenutzer' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	if( !dat->wertExistiert( "DBPasswort" ) )
	{
		std::cout << "error: Kein 'DBPasswort' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	if( !dat->wertExistiert( "DBName" ) )
	{
		std::cout << "error: Kein 'DBName' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	sql::Datenbank *db = new sql::Datenbank( dat->zWert( "DBBenutzer" )->getText(),
											 dat->zWert( "DBPasswort" )->getText(),
											 dat->zWert( "DBName" )->getText(),
											 dat->zWert( "DBIP" )->getText(),
											 (unsigned short)TextZuInt( dat->zWert( "DBPort" )->getText(), 10 ) );
	if( !db->istOk() )
	{
		Text *err = db->getLetzterFehler();
		std::cout << "error: Es konnte keine Verbindung zur datenbank hergestellt werden. Das Programm wird geschlossen.\n" << err->getText();
		err->release();
		db->release();
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 3;
	}
	std::cout << "Verbindung zur Datenbank erfolgreich Hergestellt.\n";
	std::cout << "Überprüfe ob Datenbank Server läuft...\n";
	if( !dat->wertExistiert( "DBServerIP" ) )
	{
		std::cout << "error: Kein 'DBServerIP' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		db->release();
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	if( !dat->wertExistiert( "DBServerPort" ) )
	{
		std::cout << "error: Kein 'DBServerIP' Eintrag in der startup.ini gefunden. Das Programm wird geschlossen.\n";
		db->release();
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 2;
	}
	Network::Klient *klient = new Network::Klient();
	bool b = klient->verbinde( (unsigned short)TextZuInt( dat->zWert( "DBServerPort" )->getText(), 10 ), dat->zWert( "DBServerIP" )->getText() );
	char ret = 0;
	if( b )
	{
		klient->sende( "\6", 1 );
		klient->getNachricht( &ret, 1 );
		klient->trenne();
	}
	klient = klient->release();
	if( b )
	{
		std::cout << "error: Der Datenbank Server läuft bereits. Es ist kein erneuter Start des Systems möglich. Das Programm wird geschlossen.\n";
		db->release();
		dat->release();
		file.close();
		std::cout.rdbuf( sbuf );
		Network::Exit();
		return 4;
	}

    std::cout << "App Server wird gestartet...\n";
    if( !dat->wertExistiert( "AppServerPfad" ) )
        std::cout << "warnung: Kein 'AppServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
    else
    {
        pid_t id;
        char *args[] = { ( char* )"AppServer", (char*)0 };
        chdir( dat->zWert( "AppServerPfad" )->getText() );
        posix_spawn( &id, "AppServer", 0, 0, args, 0 );
        std::cout << "App Server wurde gestartet.\n";
    }

	/*std::cout << "Chat App Server wird gestartet...\n";
	if( !dat->wertExistiert( "ChatAppServerPfad" ) )
		std::cout << "warnung: Kein 'ChatAppServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { ( char* )"ChatAppServer", (char*)0 };
		chdir( dat->zWert( "ChatAppServerPfad" )->getText() );
		posix_spawn( &id, "ChatAppServer", 0, 0, args, 0 );
		std::cout << "Chat App Server wurde gestartet.\n";
	}*/

	std::cout << "Main Server wird gestartet...\n";
	if( !dat->wertExistiert( "MainServerPfad" ) )
		std::cout << "warnung: Kein 'MainServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"MainServer", (char*)0 };
		chdir( dat->zWert( "MainServerPfad" )->getText() );
		posix_spawn( &id, "MainServer", 0, 0, args, 0 );
		std::cout << "Main Server wurde gestartet.\n";
	}

	std::cout << "Lösche Client Liste in Datenbank...\n";
	db->befehl( "SELECT id from client" );
	sql::Result r = db->getResult();
	for( int i = 0; i < r.zeilenAnzahl; i++ )
	{
		Text *befehl = new Text( "SELECT unregister_client( " );
		befehl->append( r.values[ i ].getText() );
		befehl->append( " )" );
		db->befehl( befehl->getText() );
		befehl->release();
	}
	std::cout << r.zeilenAnzahl << " Clients gelöscht.\n";
	r.destroy();

	std::cout << "Lösche laufende Spiele...\n";
	db->befehl( "SELECT id FROM spiel WHERE end_datum IS NULL" );
	r = db->getResult();
	for( int i = 0; i < r.zeilenAnzahl; i++ )
	{
		Text *befehl = new Text( "DELETE FROM spiel_spieler WHERE spiel_id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->setText( "DELETE FROM spiel WHERE id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->release();
	}
	std::cout << r.zeilenAnzahl << " laufende Spiele gelöscht.\n";
	r.destroy();

	std::cout << "Lösche erstellte Spiele...\n";
	db->befehl( "SELECT id FROM spiel_erstellt" );
	r = db->getResult();
	for( int i = 0; i < r.zeilenAnzahl; i++ )
	{
		Text *befehl = new Text( "DELETE FROM spiel_erstellt_spieler WHERE spiel_erstellt_id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->setText( "DELETE FROM spiel_erstellt_gruppe WHERE spiel_erstellt_id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->setText( "DELETE FROM spiel_erstellt WHERE id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->release();
	}
	std::cout << r.zeilenAnzahl << " erstellte Spiele gelöscht.\n";
	r.destroy();

	std::cout << "Lösche Warteschlange...\n";
	db->befehl( "DELETE FROM account_anmeldung_fuer_spiel" );
	std::cout << db->getZeilenAnzahl() << " Spieler aus der Warteschlange entfernt.\n";
	db->befehl( "DELETE FROM gruppe_anmeldung_fuer_spiel" );
	std::cout << db->getZeilenAnzahl() << " Gruppen aus der Warteschlange entfernt.\n";

	std::cout << "Lösche Gruppen...\n";
	db->befehl( "SELECT id FROM gruppe" );
	r = db->getResult();
	for( int i = 0; i < r.zeilenAnzahl; i++ )
	{
		Text *befehl = new Text( "DELETE FROM gruppe_spieler WHERE gruppe_id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->setText( "DELETE FROM gruppe WHERE id = " );
		befehl->append( r.values[ i ].getText() );
		db->befehl( befehl->getText() );
		befehl->release();
	}
	std::cout << r.zeilenAnzahl << " Gruppen gelöscht.\n";
	r.destroy();
	db->befehl("UPDATE server a SET server_status_id = 1, tasks = 0 FROM server_typ b WHERE a.server_typ_name = b.name AND b.task_name = 'clients'");
	std::cout << db->getZeilenAnzahl() << " Server zurückgesetzt.\n";

	//std::cout << "Lösche Chaträume...\n";
	//db->befehl( "SELECT id FROM chatroom" );
	//r = db->getResult();
	//for( int i = 0; i < r.zeilenAnzahl; i++ )
	//{
	//	Text *befehl = new Text( "DELETE FROM chatroom_spieler WHERE chatroom_id = " );
	//	befehl->append( r.values[ i ].getText() );
	//	db->befehl( befehl->getText() );
	//	befehl->setText( "DELETE FROM chatroom WHERE id = " );
	//	befehl->append( r.values[ i ].getText() );
	//	db->befehl( befehl->getText() );
	//	befehl->release();
	//}
	//std::cout << r.zeilenAnzahl << " Chaträume gelöscht.\n";
	//r.destroy();

	std::cout << "Starte Erhaltungs Server...\n";
	if( !dat->wertExistiert( "ErhaltungServerPfad" ) )
		std::cout << "warnung: Kein 'ErhaltungServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"ErhaltungServer", (char*)0 };
		chdir( dat->zWert( "ErhaltungServerPfad" )->getText() );
		posix_spawn( &id, "ErhaltungServer", 0, 0, args, 0 );
		std::cout << "Erhaltung Server wurde gestartet.\n";
	}

	std::cout << "Starte Patch Server...\n";
	if( !dat->wertExistiert( "PatchServerPfad" ) )
		std::cout << "warnung: Kein 'PatchServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"PatchServer", (char*)0 };
		chdir( dat->zWert( "PatchServerPfad" )->getText() );
		posix_spawn( &id, "PatchServer", 0, 0, args, 0 );
		std::cout << "Patch Server wurde gestartet.\n";
	}

	std::cout << "Starte Register Server...\n";
	if( !dat->wertExistiert( "RegisterServerPfad" ) )
		std::cout << "warnung: Kein 'RegisterServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"RegisterServer", (char*)0 };
		chdir( dat->zWert( "RegisterServerPfad" )->getText() );
		posix_spawn( &id, "RegisterServer", 0, 0, args, 0 );
		std::cout << "Register Server wurde gestartet.\n";
	}

	std::cout << "Starte Login Server...\n";
	if( !dat->wertExistiert( "LoginServerPfad" ) )
		std::cout << "warnung: Kein 'LoginServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"LoginServer", (char*)0 };
		chdir( dat->zWert( "LoginServerPfad" )->getText() );
		posix_spawn( &id, "LoginServer", 0, 0, args, 0 );
		std::cout << "Login Server wurde gestartet.\n";
	}

	std::cout << "Starte Information Server...\n";
	if( !dat->wertExistiert( "InformationServerPfad" ) )
		std::cout << "warnung: Kein 'InformationServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"InformationServer", (char*)0 };
		chdir( dat->zWert( "InformationServerPfad" )->getText() );
		posix_spawn( &id, "InformationServer", 0, 0, args, 0 );
		std::cout << "Information Server wurde gestartet.\n";
	}

	std::cout << "Starte Chat Server...\n";
	if( !dat->wertExistiert( "ChatServerPfad" ) )
		std::cout << "warnung: Kein 'ChatServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"ChatServer", (char*)0 };
		chdir( dat->zWert( "ChatServerPfad" )->getText() );
		posix_spawn( &id, "ChatServer", 0, 0, args, 0 );
		std::cout << "Chat Server wurde gestartet.\n";
	}

	std::cout << "Starte Anmeldung Server...\n";
	if( !dat->wertExistiert( "AnmeldungServerPfad" ) )
		std::cout << "warnung: Kein 'AnmeldungServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"AnmeldungServer", (char*)0 };
		chdir( dat->zWert( "AnmeldungServerPfad" )->getText() );
		posix_spawn( &id, "AnmeldungServer", 0, 0, args, 0 );
		std::cout << "Anmeldung Server wurde gestartet.\n";
    }

    std::cout << "Starte karten Server...\n";
    if( !dat->wertExistiert( "KartenServerPfad" ) )
        std::cout << "warnung: Kein 'KartenServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
    else
    {
        pid_t id;
        char *args[] = { ( char* )"KartenServer", (char*)0 };
        chdir( dat->zWert( "KartenServerPfad" )->getText() );
        posix_spawn( &id, "KartenServer", 0, 0, args, 0 );
        std::cout << "Karten Server wurde gestartet.\n";
    }

	std::cout << "Starte spiel Server...\n";
	if( !dat->wertExistiert( "SpielServerPfad" ) )
		std::cout << "warnung: Kein 'SpielServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"SpielServer", (char*)0 };
		chdir( dat->zWert( "SpielServerPfad" )->getText() );
		posix_spawn( &id, "SpielServer", 0, 0, args, 0 );
		std::cout << "Spiel Server wurde gestartet.\n";
	}

	std::cout << "Starte Shop Server...\n";
	if( !dat->wertExistiert( "ShopServerPfad" ) )
		std::cout << "warnung: Kein 'ShopServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { (char*)"ShopServer", (char*)0 };
		chdir( dat->zWert( "ShopServerPfad" )->getText() );
		posix_spawn( &id, "ShopServer", 0, 0, args, 0 );
		std::cout << "Shop Server wurde gestartet.\n";
	}

	std::cout << "Starte Historie Server...\n";
	if( !dat->wertExistiert( "HistorieServerPfad" ) )
		std::cout << "warnung: Kein 'HistorieServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { ( char* )"HistorieServer", (char*)0 };
		chdir( dat->zWert( "HistorieServerPfad" )->getText() );
		posix_spawn( &id, "HistorieServer", 0, 0, args, 0 );
		std::cout << "Historie Server wurde gestartet.\n";
	}

	std::cout << "Starte News Server...\n";
	if( !dat->wertExistiert( "NewsServerPfad" ) )
		std::cout << "warnung: Kein 'NewsServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { ( char* )"NewsServer", (char*)0 };
		chdir( dat->zWert( "NewsServerPfad" )->getText() );
		posix_spawn( &id, "NewsServer", 0, 0, args, 0 );
		std::cout << "News Server wurde gestartet.\n";
	}

	std::cout << "Starte Editor Server...\n";
	if( !dat->wertExistiert( "EditorServerPfad" ) )
		std::cout << "warnung: Kein 'EditorServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
	else
	{
		pid_t id;
		char *args[] = { ( char* )"EditorServer", (char*)0 };
		chdir( dat->zWert( "EditorServerPfad" )->getText() );
		posix_spawn( &id, "EditorServer", 0, 0, args, 0 );
		std::cout << "Editor Server wurde gestartet.\n";
	}

    std::cout << "Starte Minigame Server...\n";
    if( !dat->wertExistiert( "MinigameServerPfad" ) )
        std::cout << "warnung: Kein 'MinigameServerPfad' Eintrag in der startup.ini gefunden. Dieser Server wird nicht gestartet.\n";
    else
    {
        pid_t id;
        char *args[] = { ( char* )"MinigameServer", (char*)0 };
        chdir( dat->zWert( "MinigameServerPfad" )->getText() );
        posix_spawn( &id, "MinigameServer", 0, 0, args, 0 );
        std::cout << "Minigame Server wurde gestartet.\n";
    }

	db->release();
	dat->speichern();
	dat->release();
	std::cout << "Der Startvorgang wurde beendet.\n";
	file.close();
	std::cout.rdbuf( sbuf );
	Network::Exit();
	return 0;
}
#pragma GCC diagnostic pop 