#ifndef SpielServer_H
#define SpielServer_H

#include <Server.h>
#include <Thread.h>
#include <Datei.h>
#include <Text.h>
#include "SSKlientV.h"
#include <InitDatei.h>
#ifdef WIN32
#include "SpielErstellt/SpielErstellt.h"
#include "Spiel/Spiel.h"
#include "../Datenbank/Datenbank.h"
#include "Historie/HistorieSender.h"
#else
#include "SpielErstellt.h"
#include "Spiel.h"
#include "Datenbank.h"
#include "HistorieSender.h"
#endif

using namespace Framework;
using namespace Network;

class SSKlient;

class SpielServer : public Thread
{
private:
	HistorieSender *historieS;
	Server *server;
	SSLServer *aServer;
	InitDatei *ini;
	SSDatenbank *db;
	CRITICAL_SECTION cs;
	SpielFinden *startSpielThread;
	RCArray< SpielErstellt > *erstellt;
	int spielErstelltAnzahl;
	RCArray< Spiel > *spiele;
	int spielAnzahl;
	RCArray< SSKlient > *klients;
	Array< int > *spielHistorieId;
	Text *fehler;
	int klientAnzahl;
	int klientAnzahl2;
	int id;
	bool nichtPausiert;
	int empfangen;
	int gesendet;
	bool end;
	int ref;

public:
	// Konstruktor 
	SpielServer( InitDatei *zIni );
	// Destruktor 
	virtual ~SpielServer();
	// nicht constant
	void lock();
	void unlock();
	void runn();
	virtual void thread();
	void close();
	bool serverStarten();
	bool serverPause();
	bool serverFortsetzen();
	bool serverBeenden();
	bool setMaxSpiele( int ms );
	void addSpielErstellt( SpielErstellt *erstellt );
	void SpielErstelltAbbruch( int spielErstelltId );
	void removeSpielErstellt( int id );
	bool registerKlient( SSKlient *klient );
	bool absturzKlient( int klientId );
	bool verteileKlient( SSKlient *klient );
	void unregisterKlient( SSKlient *zKlient );
	void klientsMM( SSKlient *k );
	void addSpiel( Spiel *spiel );
	void removeSpiel( int spielId );
	void addGesendet( int bytes );
	void addEmpfangen( int bytes );
	void addSpielHistorieId( int id );
	bool hatSpielHistorieId( int id );
	void removeSpielHistorieId( int id );
	// conatant 
	bool istAn() const;
	Server *zServer() const;
	SSDatenbank *zDB() const;
    InitDatei *zInit() const;
	bool hatClients() const;
	int getId() const;
	char *getLetzterFehler() const;
	char *getIp() const;
	int getPort() const;
	// Reference Counting
	SpielServer *getThis();
	SpielServer *release();
};

class SSAKlient : public Thread
{
private:
	SSLSKlient *klient;
	Text *name;
	Text *passwort;
	int adminId;
	SpielServer *ss;
	int version;

public:
	// Konstruktor 
	SSAKlient( SSLSKlient *klient, SpielServer *ss );
	// Destruktor 
	virtual ~SSAKlient();
	// nicht constant
	void thread();
	void sendeVerzeichnisAnKlient( char *pfad, int );
	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
};

class SSKlient : public SSKlientV
{
private:
	SKlient     *empfangen;
	SKlient     *senden;
	unsigned int klientNummer;
	SpielServer *ss;
	int accountId;
	bool termThread;
	bool verbunden;
	SpielErstellt *zErstellt;
	Spiel *zSpiel;
	CRITICAL_SECTION cs;
	int ref;

public:
	// Konstruktor 
	SSKlient( SKlient *klient, SpielServer *ss );
	// Destruktor 
	virtual ~SSKlient();
	// nicht constant 
	void lock();
	void unlock();
	void absturz();
	void setSpielErstellt( SpielErstellt *zErstellt );
	void setSpiel( Spiel *zSpiel );
	virtual void nichtTrennen();
	void spielGefunden( int karteId );
	void zeitVerbleibend( char sekunden );
	void erstellungAbgebrochen( char *grund );
	void backInWarteschlange( char st, char min, char sec );
	void erstellungFortsetzen();
	void erstellungInitialisierung( SpielerTeamStruktur *sts );
	void erstellungAddSpieler( int accountId );
	void erstellungRemoveSpieler( int accountId );
	void erstellungSpielerTeam( int accountId, int spielerNummer );
	void erstellungChatNachricht( char *nachricht );
	void spielLadenBeginn();
	void spielLadenSpielerAdd( int accId, int spielerNumer );
	void spielLadenSetSpielerProzent( int accId, int prozent );
	void spielLadenSetSpielerPing( int accId, int ping );
	virtual double ping();
	void spielLadenFertig();
	virtual void spielNachricht( short len, char *bytes );
	virtual void statistikNachricht( short len, char *bytes );
	bool keepAlive();
	virtual void trenne();
	void setSenden( SSKlient *klient );
	virtual void thread();
	virtual void errorZuKlientEmpfang( const char *nachricht ); // sendet eine Fehlernachricht zum Klient
	virtual void errorZuKlientSende( const char *nachricht );
	// const
	virtual int getAccountId() const;
	int getKlientNummer() const;
	SKlient *getKlient() const;
	// Reference Counting
	virtual SSKlientV *getThis();
	virtual SSKlientV *release();
};

#endif