#include <main.h>
#include <Datei.h>
#include <Fenster.h>
#include <Globals.h>
#include <InitDatei.h>
#include <KSGNetwork.h> 

int KSGStart Framework::Start( Startparam p )
{
    Network::Start( 10 );
    char serverReturn = 0;

    HANDLE Mutex = OpenMutex( MUTEX_ALL_ACCESS, false, "KSG_Client" );
    if( Mutex == NULL )
    {
        Mutex = CreateMutex( NULL, true, "KSG_Client" );
        DateiRemove( new Text( "data/tmp/k.id" ) );
        DateiRemove( new Text( "data/tmp/keinabsturz" ) );
    }
    else
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Das Programm läuft bereits. Wenn dieß nicht der Fall ist,\nmusst du den Komputer neu starten." ), MB_ICONERROR );
        Network::Exit();
        return 0;
    }

    if( DateiExistiert( new Text( "data/update/unable/list.patch" ) ) )
    {
        PROCESS_INFORMATION prozessinfo3;
        STARTUPINFO startinfo3;
        ZeroMemory( &startinfo3, sizeof( STARTUPINFOW ) );
        startinfo3.cb = sizeof( STARTUPINFOW );

        if( CreateProcess( 0, "data/patch/bin/übernehmen.exe", 0, 0, 0, 0, 0, 0, &startinfo3, &prozessinfo3 ) == 1 )
        {
            Network::Exit();
            DateiRemove( new Text( "data/tmp" ) );
            exit( 0 );
        }
        else
        {
            WMessageBox( 0, new Text( "Fehler" ), new Text( "Bei dem Übernehen der Änderungen ist ein Fehler aufgetreten.\nBitte starte den Komputer neu. Sollte diese Meldung weiterhin\nerscheinen, so musst du das Spiel neu Installieren." ), MB_ICONERROR );
            exit( 0 );
        }
    }

    PROCESS_INFORMATION prozessinfo1;
    STARTUPINFO startinfo1;
    startinfo1.cb = sizeof( STARTUPINFOW );
    ZeroMemory( &startinfo1, sizeof( STARTUPINFOW ) );
    bool pe = 0;

    if( CreateProcess( 0, "data/start/icon.exe", 0, 0, 0, 0, 0, 0, &startinfo1, &prozessinfo1 ) == 1 )
    {
        CloseHandle( prozessinfo1.hThread );
        pe = 1;
    }

    // Laden des Main Clients
    HINSTANCE networkDLL = LoadLibrary( "data/bin/KSGNetwork.dll" );
    if( !networkDLL )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Die DLL Datei 'data/bin/KSGNetwork.dll' konnte nicht geladen werden. Fallst diese Datei nicht existiert muss das Spiel neu Installiert werden." ), MB_ICONERROR );
        exit( 0 );
    }
    KSGClient::KSGNetworkCreateMain getMainClient = ( KSGClient::KSGNetworkCreateMain )GetProcAddress( networkDLL, KSGNETWORK_CREATE_MAIN );
    if( !getMainClient )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Der Einstiegspunkt '" KSGNETWORK_CREATE_MAIN "' wurde in der DLL Datei 'data/bin/KSGNetwork.dll' nicht gefunden. Fallst dieses Problem weiterhin auftritt muss das Spiel neu Installiert werden." ), MB_ICONERROR );
        exit( 0 );
    }
    KSGClient::MainServerClient *mainClient = getMainClient();
    if( !mainClient )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Die DLL Datei 'data/bin/KSGNetwork.dll' scheint fehlerhaft zu sein. Fallst dieses Problem weiterhin auftritt muss das Spiel neu Installiert werden." ), MB_ICONERROR );
        exit( 0 );
    }

    // Laden der Adresse des Main Servers
    InitDatei *iDat = new InitDatei( "data/optionen.ini" );
    iDat->laden();
    if( !iDat->zWert( "ServerIP" ) )
        iDat->addWert( "ServerIP", "127.0.0.1" );
    if( !iDat->zWert( "ServerPort" ) )
        iDat->addWert( "ServerPort", "4225" );
    iDat->speichern();
    Text *ipT = iDat->zWert( "ServerIP" );
    unsigned short port = (unsigned short)TextZuInt( iDat->zWert( "ServerPort" )->getText(), 10 );
    iDat->release();

    // Registrieren beim Server
    if( !mainClient->registerSSL( ipT->getText(), port ) )
    {
        Text err = "Fehler beim Registrieren des Clients: ";
        err += mainClient->getLetzterFehler();
        WMessageBox( 0, new Text( "Fehler" ), err.getThis(), MB_ICONERROR );
        exit( 0 );
    }

    // Speichere Server Adresse für andere Anwendungen
    int klientNummer = mainClient->getClientId();
    Datei *dat = new Datei();
    dat->setDatei( "data/tmp/k.id" );
    dat->erstellen();
    dat->open( Datei::Style::schreiben );
    dat->schreibe( (char*)&klientNummer, 4 );
    dat->close();
    dat->setDatei( "data/tmp/m.port" );
    dat->erstellen();
    dat->open( Datei::Style::schreiben );
    int normPort = mainClient->getServerPort();
    dat->schreibe( (char*)&normPort, 4 );
    dat->close();
    dat->setDatei( "data/tmp/m.ip" );
    dat->erstellen();
    dat->open( Datei::Style::schreiben );
    char *serverIp = mainClient->getServerIp();
    unsigned char len = (unsigned char)textLength( serverIp );
    dat->schreibe( (char*)&len, 1 );
    dat->schreibe( (char*)&serverIp, len );
    dat->close();
    dat->release();

    KSGClient::ErhaltungServerClient *erhaltung = mainClient->createErhaltungServerClient();
    if( !erhaltung )
    {
        Text err = "Fehler beim erstellen des Erhaltung Servers: ";
        err += mainClient->getLetzterFehler();
        WMessageBox( 0, new Text( "Warnung" ), err.getThis(), MB_ICONWARNING );
    }
    else
    {
        if( !erhaltung->verbinde() )
        {
            Text err = "Fehler beim verbinden mit dem Erhaltung Server: ";
            err += erhaltung->getLetzterFehler();
            WMessageBox( 0, new Text( "Warnung" ), err.getThis(), MB_ICONWARNING );
        }
    }

    if( pe )
    {
        while( WaitForSingleObject( prozessinfo1.hProcess, 1000 ) == WAIT_TIMEOUT );
        CloseHandle( prozessinfo1.hProcess );
    }

    PROCESS_INFORMATION prozessinfo2;
    STARTUPINFO startinfo2;
    startinfo2.cb = sizeof( STARTUPINFOW );
    ZeroMemory( &startinfo2, sizeof( STARTUPINFOW ) );

    if( CreateProcess( 0, "data/patch/bin/patcher.exe", 0, 0, 0, 0, 0, 0, &startinfo2, &prozessinfo2 ) == 1 )
    {
        CloseHandle( prozessinfo2.hThread );
        while( WaitForSingleObject( prozessinfo2.hProcess, 5000 ) == WAIT_TIMEOUT );
        unsigned long erfolg = 0;
        GetExitCodeProcess( prozessinfo2.hProcess, &erfolg );
        if( erfolg != 0 && DateiExistiert( new Text( "data/tmp/keinabsturz" ) ) )
        {
            bool gamestart = erfolg == 2;
            if( erfolg == 1 )
            {
                PROCESS_INFORMATION prozessinfo3;
                STARTUPINFO startinfo3;
                startinfo3.cb = sizeof( STARTUPINFOW );
                ZeroMemory( &startinfo3, sizeof( STARTUPINFOW ) );

                if( CreateProcess( 0, "data/patch/bin/übernehmen.exe", 0, 0, 0, 0, 0, 0, &startinfo3, &prozessinfo3 ) == 1 )
                {
                    // Trenne Verbindung zum Server
                    if( erhaltung )
                    {
                        if( DateiExistiert( new Text( "data/tmp/keinabsturz" ) ) )
                            erhaltung->abmelden();
                        erhaltung->trenne();
                        erhaltung->release();
                    }
                    mainClient->unregister();
                    mainClient->release();

                    ipT->release();
                    Network::Exit();

                    DateiRemove( new Text( "data/tmp" ) );

                    exit( 0 );
                }
                else
                    gamestart = 0;
                if( !gamestart )
                    WMessageBox( 0, new Text( "Fehler" ), new Text( "Bei dem Übernehen der Änderungen ist ein Fehler aufgetreten." ), MB_ICONERROR );
            }
            if( gamestart )
            {
                PROCESS_INFORMATION prozessinfo3;
                STARTUPINFO startinfo3;
                startinfo3.cb = sizeof( STARTUPINFOW );
                ZeroMemory( &startinfo3, sizeof( STARTUPINFOW ) );
                DateiRemove( new Text( "data/tmp/keinabsturz" ) );

                if( CreateProcess( 0, "\"data/client/bin/game client.exe\"", 0, 0, 0, 0, 0, 0, &startinfo3, &prozessinfo3 ) == 1 )
                {
                    CloseHandle( prozessinfo3.hThread );
                    while( WaitForSingleObject( prozessinfo3.hProcess, 5000 ) == WAIT_TIMEOUT );
                    CloseHandle( prozessinfo3.hProcess );
                }
                else
                    WMessageBox( 0, new Text( "Fehler" ), new Text( "Das Spiel konnte nicht gestartet werden." ), MB_ICONERROR );
            }
        }
        CloseHandle( prozessinfo2.hProcess );
    }
    else
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Der Patcher konnte nicht gestartet werden." ), MB_ICONERROR );
    }
    // Verbindung zum Server Trennen
    if( DateiExistiert( new Text( "data/tmp/keinabsturz" ) ) )
        erhaltung->abmelden();
    erhaltung->trenne();
    erhaltung->release();
    mainClient->unregister();
    mainClient->release();

    ipT->release();
    Network::Exit();

    DateiRemove( new Text( "data/tmp" ) );

    return 0;
}