#ifndef ChatServer_H
#define ChatServer_H

#include <Server.h>
#include <Thread.h>
#include <Datei.h>
#include <Text.h>
#include <InitDatei.h>
#include "Datenbank.h"
#include <Klient.h>

using namespace Framework;
using namespace Network;

class CSKlient;
class KlientArray;

class ChatServer : public Thread
{
private:
	Server *server;
	Server *aServer;
	InitDatei *ini;
	CSDatenbank *db;
	Critical cs;
	RCArray< CSKlient > *klients;
	Text *fehler;
	int klientAnzahl;
	int id;
	bool nichtPausiert;
	int empfangen;
	int gesendet;
	bool end;
	int ref;

public:
	// Konstruktor 
	ChatServer( InitDatei *zIni );
	// Destruktor 
	virtual ~ChatServer();
	// nicht constant 
	void runn();
	void thread();
	void close();
	bool serverStarten();
	bool serverPause();
	bool serverFortsetzen();
	bool serverBeenden();
	bool setMaxKlients( int mc );
	bool absturzKlient( int klientId );
	bool removeAccount( int accId );
	bool removeKlient( int klientId );
	bool removeKlient( CSKlient *zKlient );
	void addGesendet( int bytes );
	void addEmpfangen( int bytes );
	int getKlientStatus( int klientNummer, CSKlient *zKlient );
	CSKlient *zSendeKlient( int accountId );
	// conatant 
	bool istAn() const;
	Server *zServer() const;
	CSDatenbank *zDB() const;
	bool hatClients() const;
	int getId() const;
	char *getLetzterFehler() const;
	// Reference Counting
	ChatServer *getThis();
	ChatServer *release();
};

class CSAKlient : public Thread
{
private:
	SKlient *klient;
	Text *name;
	Text *passwort;
	int adminId;
	ChatServer *cs;

public:
	// Konstruktor 
	CSAKlient( SKlient *klient, ChatServer *cs );
	// Destruktor 
	virtual ~CSAKlient();
	// nicht constant
	void thread();
	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
};

class CSKlient : public Thread
{
private:
	SKlient *klient;
	unsigned int klientNummer;
	unsigned int accountId;
	ChatServer *cs;
	Critical ts;
	bool empfangen;
	int ref;

public:
	// Konstruktor 
	CSKlient( SKlient *klient, ChatServer *cs );
	// Destruktor 
	virtual ~CSKlient();
	// nicht constant 
	void lock();
	void unlock();
	void absturz();
	void thread();
	bool kick();
	bool nachricht( int vonAccount, const char *txt );
	bool gruppeEinladung( int vonAccount, int gruppeId );
	bool accountStatusChange( int account, const char *status );
	bool accountNameChange( int account, const char *name );
	bool keinFreundMehr( int account );
	bool freundesAnfrage( int vonAccount );
	bool neuerFreund( int account );
	bool freundesAnfrageAbgelehnt( int account );
	bool einladungZumChatroom( int vonAccount, int chatroomId );
	bool einladungZumChatroomAbgelehnt( int account, int chatroomId );
	bool spielerBetrittChatroom( int chatroomId, int account );
	bool chatroomNachricht( int chatroomId, int vonAccount, const char *nachricht );
	bool spielerLeavesChatroom( int chatroomId, int accountId );
	bool freunde( char anzahl, Array< int > *zAccountId );
	bool spielerImChatroom( int chatroomId, char anzahl, Array< int > *zAccountId );
	bool freundOnline( int accountId );
	bool freundOffline( int accountId );
	bool chatroomAdmin( int chatroomId );
	bool chatroomKick( int chatroomId );
	bool spielerBertittGruppe( int accountId, int gruppeId );
	bool spielerLeavesGruppe( int accountId, int gruppeId );
	bool gruppeNachricht( int gruppeId, char *nachricht );
	bool gruppeAnmelden( int gruppeId );
	bool gruppeAbmelden( int gruppeID );
	bool gruppeSpielStarten( int gruppeId, bool starten );
	bool setGruppeAdmin( int gruppeId, int adminId );
	bool kickAusGruppe( int gruppeId );
	bool gruppeEinladungAbgelehnt( int gruppeId, int accountId );
	bool spielServerVerbindungsAnfrage( unsigned short port, unsigned char *ip );
	bool gruppeEinladungAbgebrochen( int gruppeId, int accountId );
	bool gruppeEinladungNeu( int gruppeId, int accountId );
	bool errorZuKlient( const char *nachricht ); // sendet eine Fehlernachricht zum Klient
	bool keepAlive(); // erhält die Verbindung aufrecht
	void trenne();
	// constant
	int getKlientNummer() const;
	int getAccountId() const;
	bool istEmpfang() const;
	// Reference Counting
	CSKlient *getThis();
	CSKlient *release();
};

class MSGWeiterleitung
{
private:
	ChatServer *cs;
	Klient *klient;
	Text *letzterFehler;

public:
	// Konstruktor
	MSGWeiterleitung( ChatServer *cs );
	// Destruktor
	~MSGWeiterleitung();
	// nicht constant
	bool kickKlient( int accountId );
	bool accountOnline( int accountId );
	bool accountOffline( int accountId );
	bool chatNachricht( int vonAccount, int zuAccount, const char *nachricht );
	bool accountStatusChange( int accountId, const char *status );
	bool accountNameChange( int accountId, const char *name );
	bool accountKeinFreundMehr( int accountId, int zielAccountId );
	bool freundesAnfrage( int vonAccountId, int zuAccountId );
	bool neuerFreund( int accountId, int zuAccountId );
	bool einladungZumChatroom( int vonAccountId, int zuAccountId, int chatroomId );
	bool spielerBetrittChatroom( int accountId, int chatroomId );
	bool chatroomNachricht( int vonAccount, const char *nachricht, int chatroomId );
	bool spielerLeavestChatroom( int accountId, int chatroomId );
	bool freundEinladungAbgelehnt( int accountId, int zuAccountId );
	bool chatroomEinladungAbgelehnt( int accountId, int chatroomId, int zuAccountId );
	bool chatroomAdmin( int chatroomId, int zuAccountId );
	bool chatroomKick( int chatroomId, int accountId );
	bool fehler( int zuAccountId, const char *fehler );
	// constant
	const char *getLetzterFehler();
};

#endif