#include "Patcher.h"
#include <Datei.h>
#include <Text.h>
#include <InitDatei.h>
#include <Text.h>
#include <GSLDateiV.h>

typedef UpdaterV *( *GetUpdater )( KSGClient::PatchServerClient * );
typedef GSL::GSLDateiV *( *GetGSLDatei )( );

// Inhalt der Patcher Klasse aus Patcher.h
// Konstruktor
Patcher::Patcher( FBalken *fortschritt, TextFeld *status, Knopf *play, bool *close, KSGClient::PatchServerClient *client )
	: Thread()
{
    if( !client )
    {
        updater = 0;
        MessageBox( 0, "Es steht kein Patch Client zur Verfügung.", "Fehler", MB_ICONERROR );
    }
    else
    {
        // Dll Laden
        updateDll = LoadLibrary( "data/bin/update.dll" );
        if( !updateDll )
        {
            updater = 0;
            MessageBox( 0, "Die DLL Datei 'data/bin/update.dll' wurde nicht gefunden.", "Fehler", MB_ICONERROR );
        }
        else
        {
            GetUpdater getUpdater = (GetUpdater)GetProcAddress( updateDll, "getUpdater" );
            if( !getUpdater )
            {
                updater = 0;
                MessageBox( 0, "Der Einstiegspunkt 'getUpdater' konnte in der DLL Datei 'data/bin/update.dll' nicht gefunden.", "Fehler", MB_ICONERROR );
            }
            else
                updater = getUpdater( client );
        }
        if( !updater )
            client->release();
    }
	// Initialisierung
	this->fortschritt = fortschritt;
	this->status = status;
	this->play = play;
	this->close = close;
	ret = 0;
}

// Destruktor
Patcher::~Patcher()
{
	if( run )
	{
		*close = 1;
		warteAufPatch( 5000 );
	}
	if( run )
		ende();
	fortschritt->release();
	status->release();
	play->release();
	if( updater )
		updater->release();
	FreeLibrary( updateDll );
}

// nicht constant
void Patcher::startPatch()
{
	start();
}

void Patcher::thread()
{
	if( !updater )
	{
		status->lockZeichnung();
		status->setText( "Es ist ein schwerer Fehler aufgetreten!" );
		status->unlockZeichnung();
		run = 0;
		return;
	}
	status->lockZeichnung();
	status->setText( "Suche nach Updates . . ." );
	status->unlockZeichnung();
	Text dgPfad;
	int gruppe = updater->getNextDateiGruppe( &dgPfad ); // Nächste Dateigruppe die geupdatet werden muss
	while( gruppe )
	{
		if( gruppe == -1 )
		{ // error
			status->lockZeichnung();
			status->setText( "Es ist ein schwerer Fehler aufgetreten!" );
			status->unlockZeichnung();
			MessageBox( 0, updater->getError(), "Fehler", MB_ICONERROR );
			run = 0;
			return;
		}
		bool clientGruppe = !dgPfad.getLength();
		if( !clientGruppe )
		{ // Das Spiel kann bereits gestartet werden
			play->addStyle( Knopf::Style::Sichtbar );
			ret = 2;
		}
		status->lockZeichnung();
		status->setText( "Update für '" );
		if( !clientGruppe )
			status->zText()->append( dgPfad.getText() );
		else
			status->zText()->append( "Client" );
		status->zText()->append( "'. . ." );
		status->unlockZeichnung();
		UpdateParams params;
		params.abbruch = close;
		params.dateiGruppe = gruppe;
		params.zFortschritt = fortschritt;
		params.zStatus = 0;
		int res = updater->update( &params );
		if( res == 3 )
		{ // es gibt Dateien, die der Patcher (wegen momentaner Benutzung) nicht pätchen konnte
			status->lockZeichnung();
			status->setText( "Klicke auf Play, um die verbleibenen Änderungen zu übernehmen." );
			status->unlockZeichnung();
			play->addStyle( Knopf::Style::Sichtbar );
			ret = 1;
			run = 0;
			return;
		}
		if( res == 2 )
			break;
		if( res == 1 )
			MessageBox( 0, updater->getError(), "Fehler", MB_ICONERROR );
		status->lockZeichnung();
		status->setText( "Suche nach Updates . . ." );
		status->unlockZeichnung();
		gruppe = updater->getNextDateiGruppe( &dgPfad );
	}
	status->lockZeichnung();
	status->setText( "Alle ausgewählten Dateien sind aktuell." );
	status->unlockZeichnung();
	play->addStyle( Knopf::Style::Sichtbar );
	ret = 2;
	HMODULE sDll = LoadLibrary( "data/bin/GSL.dll" );
	if( sDll )
	{
		GetGSLDatei getGSLDatei = (GetGSLDatei)GetProcAddress( sDll, "getGSLDatei" );
		if( getGSLDatei )
		{
			GSL::GSLDateiV *sDatei = getGSLDatei();
			sDatei->setDatei( "data/sounds/popup.gsl" );
			sDatei->leseDaten();
			GSL::GSLSoundV *sound = sDatei->getSound( "info.wav" );
			sDatei->release();
			sound->setVolume( 0xFFFF, 0xFFFF );
			sound->playSound();
			sound->warteAufSound( 3000 );
			sound->stopSound();
			sound->release();
		}
		FreeLibrary( sDll );
	}
	run = 0;
}

// constant
bool Patcher::läuftPatch() const
{
	return run;
}

int Patcher::getReturn() const
{
	return ret;
}

void Patcher::warteAufPatch( int zeit )
{
	warteAufThread( zeit );
}

int Patcher::getDownload() const
{
	return updater ? updater->getDownload() : 0;
}

// Reference Counting
Patcher *Patcher::getThis()
{
	ref++;
	return this;
}

Patcher *Patcher::release()
{
	ref--;
	if( !ref )
		delete this;
	return 0;
}