#include "StatistikChat.h"
#include <Punkt.h>
#include <DateiSystem.h>
#include <MausEreignis.h>
#include <AlphaFeld.h>
#include <Scroll.h>
#include <Rahmen.h>
#include <TastaturEreignis.h>
#include "../../Initialisierung/Initialisierung.h"

// Inhalt der ChatListeSpieler Klasse aus StatistikChat.h
// Konstruktor
ChatListeSpieler::ChatListeSpieler( int accountId, int eigeneId, Schrift *zSchrift, BilderV *bilder, KSGClient::InformationServerClient *zInfoc,
									bool istFreund, void( *addChatF )( void*, int ), void( *addFreundF )( void*, int ),
									void( *accountAnsehenF )( void *, int ), void *param )
									: addChatF( addChatF ),
									addFreundF( addFreundF ),
									accountAnsehenF( accountAnsehenF ),
									nachrichtParam( param ),
									accountId( accountId ),
									bg( new AlphaFeld() ),
									name( initTextFeld( 0, 0, 133, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Rahmen | TextFeld::Style::VCenter, "" ) ),
									accountAnsehen( initKnopf( 133, 0, 20, 20, 0, 0, "" ) ),
									nachrichtSenden( initKnopf( 153, 0, 20, 20, 0, 0, "" ) ),
									freundesanfrageSenden( initKnopf( 173, 0, 20, 20, 0, 0, "" ) ),
									pos( 0, 0 ),
									gr( 133, 20 ),
									online( 1 ),
									minKnopfX( 113 - ( ( ( accountId != eigeneId ) + !istFreund ) * 20 ) ),
									knopfX( 133 ),
									mausIn( 0 ),
									tickVal( 0 ),
									rend( 0 ),
									ref( 1 )
{
	Bild *ansehenBild = bilder->get( "chat.ltdb/ansehen.png" );
	if( !ansehenBild )
	{
		LTDBDatei *datei = new LTDBDatei();
		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
		datei->leseDaten( 0 );
		ansehenBild = datei->laden( 0, new Text( "ansehen.png" ) );
		datei->release();
		bilder->add( "chat.ltdb/ansehen.png", ansehenBild->getThis() );
	}
	Bild *nachrichtBild = bilder->get( "chat.ltdb/nachricht.png" );
	if( !nachrichtBild )
	{
		LTDBDatei *datei = new LTDBDatei();
		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
		datei->leseDaten( 0 );
		nachrichtBild = datei->laden( 0, new Text( "nachricht.png" ) );
		datei->release();
		bilder->add( "chat.ltdb/nachricht.png", nachrichtBild->getThis() );
	}
	Bild *einladungBild = bilder->get( "chat.ltdb/neuerfreund.png" );
	if( !nachrichtBild )
	{
		LTDBDatei *datei = new LTDBDatei();
		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
		datei->leseDaten( 0 );
		einladungBild = datei->laden( 0, new Text( "neuerfreund.png" ) );
		datei->release();
		bilder->add( "chat.ltdb/neuerfreund.png", einladungBild->getThis() );
	}
	bg->setSize( gr );
	bg->setFarbe( 0x0000FF00 );
	bg->setStrength( -4 );
	name->setText( zInfoc->getSpielerName( accountId ) );
	accountAnsehen->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	accountAnsehen->setHintergrundBildZ( ansehenBild );
	nachrichtSenden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	nachrichtSenden->setHintergrundBildZ( nachrichtBild );
	freundesanfrageSenden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	freundesanfrageSenden->setHintergrundBildZ( einladungBild );
}

// Destruktor
ChatListeSpieler::~ChatListeSpieler()
{
	bg->release();
	name->release();
	accountAnsehen->release();
	nachrichtSenden->release();
	freundesanfrageSenden->release();
}

// nicht constant
void ChatListeSpieler::setOffline()
{
	online = 0;
}

void ChatListeSpieler::setPosition( int y )
{
	if( pos.y != y )
		rend = 1;
	pos.y = y;
}

void ChatListeSpieler::doMausEreignis( MausEreignis &me )
{
	int mx = me.mx;
	int my = me.my;
	me.mx -= pos.x;
	me.my -= pos.y;
	if( me.mx > 0 && me.mx < gr.x && me.my > 0 && me.my < gr.y )
		mausIn = 1;
	else
		mausIn = 0;
	me.mx += 133 - knopfX;
	bool vera = me.verarbeitet;
	accountAnsehen->doMausEreignis( me );
	int aktion = ( me.verarbeitet && !vera ) ? 1 : 0;
	nachrichtSenden->doMausEreignis( me );
	aktion = ( me.verarbeitet && !vera && !aktion ) ? 2 : aktion;
	freundesanfrageSenden->doMausEreignis( me );
	aktion = ( me.verarbeitet && !vera && !aktion ) ? 3 : aktion;
	me.mx -= 133 - knopfX;
	if( me.id == ME_RLinks && mausIn )
	{
		switch( aktion )
		{
		case 1:
			accountAnsehenF( nachrichtParam, accountId );
			break;
		case 2:
			addChatF( nachrichtParam, accountId );
			break;
		case 3:
			addFreundF( nachrichtParam, accountId );
			break;
		}
	}
	me.mx = mx;
	me.my = my;
}

bool ChatListeSpieler::tick( double tickVal )
{
	rend |= name->tick( tickVal );
	rend |= accountAnsehen->tick( tickVal );
	rend |= nachrichtSenden->tick( tickVal );
	rend |= freundesanfrageSenden->tick( tickVal );
	this->tickVal += tickVal * 60;
	int val = ( int )this->tickVal;
	if( val )
	{
		this->tickVal -= val;
		if( mausIn && knopfX != minKnopfX )
		{
			if( knopfX - val < minKnopfX )
				knopfX = minKnopfX;
			else
				knopfX -= val;
			rend = 1;
		}
		if( !mausIn && knopfX != gr.x )
		{
			if( knopfX + val > gr.x )
				knopfX = gr.x;
			else
				knopfX += val;
			rend = 1;
		}
		if( !online && bg->getFarbe() != 0x00FF0000 )
		{
			int g = ( bg->getFarbe() >> 8 ) & 0xFF;
			if( g - val < 0 )
				bg->setFarbe( 0x00FF0000 );
			else
			{
				bg->setFarbe( ( ( ( g - val ) << 8 ) & 0xFF00 ) | ( bg->getFarbe() & 0xFFFF00FF ) );
				bg->setFarbe( ( ( ( 255 - ( g - val ) ) << 16 ) & 0xFF0000 ) | ( bg->getFarbe() & 0xFF00FFFF ) );
			}
			rend = 1;
		}
	}
	bool ret = rend;
	rend = 0;
	return ret;
}

void ChatListeSpieler::render( Bild &zRObj )
{
	if( !zRObj.setDrawOptions( pos, gr ) )
		return;
	bg->render( zRObj );
	name->render( zRObj );
	zRObj.addScrollOffset( 133 - knopfX, 0 );
	accountAnsehen->render( zRObj );
	nachrichtSenden->render( zRObj );
	freundesanfrageSenden->render( zRObj );
	zRObj.releaseDrawOptions();
}

// constant
int ChatListeSpieler::getAccountId() const
{
	return accountId;
}

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

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


// Inhalt der ChatListe Klasse aus StatistikChat.h
// Konstruktor
ChatListe::ChatListe( int eigeneId, KSGClient::InformationServerClient *infoc, Schrift *schrift, BilderV *bilder,
					  void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
					  void( *accountAnsehen )( void *, int ), void *param )
					  : addChat( addChat ),
					  addFreund( addFreund ),
					  accountAnsehen( accountAnsehen ),
					  nachrichtParam( nachrichtParam ),
					  eigeneId( eigeneId ),
					  spieler( new RCArray< ChatListeSpieler >() ),
					  vScroll( new VScrollBar() ),
					  pos( 620, 295 ),
					  gr( 150, 150 ),
					  infoc( infoc ),
					  schrift( schrift ),
					  bilder( bilder ),
					  ram( new LRahmen() ),
					  rend( 0 ),
					  ref( 1 )
{
	vScroll->setKlickScroll( 10 );
	vScroll->update( 0, 148 );
	ram->setFarbe( 0xFFFFFFFF );
	ram->setSize( 150, 150 );
}

// Destruktor
ChatListe::~ChatListe()
{
	spieler->release();
	vScroll->release();
	infoc->release();
	schrift->release();
	ram->release();
}

// nicht constant
void ChatListe::addSpieler( int accountId, bool istFreund )
{
	int anz = spieler->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( spieler->z( i ) && spieler->z( i )->getAccountId() == accountId )
			return;
	}
	ChatListeSpieler *s = new ChatListeSpieler( accountId, eigeneId, schrift, bilder, infoc, istFreund, addChat, addFreund, accountAnsehen, nachrichtParam );
	s->setPosition( anz * 20 );
	spieler->add( s );
	rend = 1;
}

void ChatListe::setOffline( int accountId )
{
	int anz = spieler->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( spieler->z( i ) && spieler->z( i )->getAccountId() == accountId )
		{
			spieler->z( i )->setOffline();
			return;
		}
	}
}

void ChatListe::doMausEreignis( MausEreignis &me )
{
	int mx = me.mx;
	int my = me.my;
	me.mx -= pos.x;
	me.my -= pos.y - vScroll->getScroll();
	vScroll->doMausMessage( 134, 1, 15, 148, me );
	int anz = spieler->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( spieler->z( i ) )
			spieler->z( i )->doMausEreignis( me );
	}
	me.mx = mx;
	me.my = my;
}

bool ChatListe::tick( double tickVal )
{
	rend |= vScroll->getRend();
	int anz = spieler->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( spieler->z( i ) )
			rend |= spieler->z( i )->tick( tickVal );
	}
	bool ret = rend;
	rend = 0;
	return ret;
}

void ChatListe::render( Bild &zRObj )
{
	if( !zRObj.setDrawOptions( pos, gr ) )
		return;
	int anz = spieler->getEintragAnzahl();
	zRObj.addScrollOffset( 0, vScroll->getScroll() );
	for( int i = 0; i < anz; i++ )
	{
		if( spieler->z( i ) )
			spieler->z( i )->render( zRObj );
	}
	zRObj.addScrollOffset( 0, -vScroll->getScroll() );
	vScroll->render( 134, 1, 15, 148, zRObj );
	ram->render( zRObj );
	zRObj.releaseDrawOptions();
}

// constant

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

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


// Inhalt der StatistikChat Klasse aus StatistikChat.h
// Konstruktor
StatistikChat::StatistikChat( int eigeneId, KSGClient::SpielServerClient *spielc, KSGClient::InformationServerClient *infoc, Schrift *schrift, BilderV *bilder,
							  void( *addNachricht )( void *, Text *, Text *, Text *, Text * ),
							  void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
							  void( *accountAnsehen )( void *, int ), void *param )
							  : addNachricht( addNachricht ),
							  nachrichtParam( nachrichtParam ),
							  spielc( spielc ),
							  infoc( infoc ),
							  verlauf( initTextFeld( 10, 295, 600, 150, schrift, TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen | TextFeld::Style::VScroll | TextFeld::Style::Mehrzeilig, "" ) ),
							  nachricht( initTextFeld( 10, 450, 575, 20, schrift, TextFeld::Style::TextFeld, "" ) ),
							  senden( initKnopf( 590, 450, 20, 20, 0, 0, "" ) ),
							  verlassen( initKnopf( 630, 450, 130, 20, schrift, Knopf::Style::Sichtbar, "Verlassen" ) ),
							  spielerListe( new ChatListe( eigeneId, infoc->getThis(), schrift, bilder, addChat, addFreund, accountAnsehen, nachrichtParam ) ),
							  beenden( 0 ),
							  ref( 1 )
{
	Bild *sendenBild = bilder->get( "chat.ltdb/senden.png" );
	if( !sendenBild )
	{
		LTDBDatei *datei = new LTDBDatei();
		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
		datei->leseDaten( 0 );
		sendenBild = datei->laden( 0, new Text( "senden.png" ) );
		datei->release();
		bilder->add( "chat.ltdb/senden.png", sendenBild->getThis() );
	};
	senden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	senden->setHintergrundBildZ( sendenBild );
}

// Destruktor
StatistikChat::~StatistikChat()
{
	spielc->release();
	infoc->release();
	verlauf->release();
	nachricht->release();
	senden->release();
	verlassen->release();
	spielerListe->release();
}

// nicht constant
void StatistikChat::addSpieler( int accountId, bool istFreund )
{
	spielerListe->addSpieler( accountId, istFreund );
}

void StatistikChat::spielerOffline( int accountId )
{
	spielerListe->setOffline( accountId );
}

void StatistikChat::addChatNachricht( int vonAccount, char *nachricht )
{
	Text *txt = vonAccount ? infoc->getSpielerName( vonAccount ) : 0;
	if( !txt )
		txt = new Text();
	else
		*txt += ": ";
	*txt += nachricht;
	*txt += "\n";
	verlauf->zSchrift()->textFormatieren( txt, verlauf->getBreite() - 15, 12 );
	verlauf->zText()->append( txt );
	verlauf->updateVScroll();
}

void StatistikChat::doMausEreignis( MausEreignis &me )
{
	verlauf->doMausEreignis( me );
	nachricht->doMausEreignis( me );
	spielerListe->doMausEreignis( me );
	bool vera = me.verarbeitet;
	senden->doMausEreignis( me );
	int aktion = ( me.verarbeitet && !vera ) ? 1 : 0;
	verlassen->doMausEreignis( me );
	aktion = ( me.verarbeitet && !vera && !aktion ) ? 2 : aktion;
	if( me.id == ME_RLinks )
	{
		if( aktion == 1 )
		{
			if( nachricht->zText()->getLength() )
			{
				short l�n = 1 + nachricht->zText()->getLength();
				char *bytes = new char[ l�n ];
				bytes[ 0 ] = 1;
				for( int i = 0; i < l�n - 1; i++ )
					bytes[ i + 1 ] = nachricht->zText()->getText()[ i ];
				if( !spielc->statistikNachricht( l�n, bytes ) )
					addNachricht( nachrichtParam, new Text( "Fehler" ), new Text( "Die Nachricht konnte nicht gesendet werden." ), new Text( "Ok" ), 0 );
				else
				{
					nachricht->setAuswahl( 0, 0 );
					nachricht->setText( "" );
				}
				delete[] bytes;
			}
		}
		if( aktion == 2 )
			beenden = 1;
	}
}

void StatistikChat::doTastaturEreignis( TastaturEreignis &te )
{
	bool vera = te.verarbeitet;
	nachricht->doTastaturEreignis( te );
	if( !vera && te.verarbeitet && te.id == TE_Release && te.taste == T_Enter )
	{
		if( nachricht->zText()->getLength() )
		{
			short l�n = 1 + nachricht->zText()->getLength();
			char *bytes = new char[ l�n ];
			bytes[ 0 ] = 1;
			for( int i = 0; i < l�n - 1; i++ )
				bytes[ i + 1 ] = nachricht->zText()->getText()[ i ];
			if( !spielc->statistikNachricht( l�n, bytes ) )
				addNachricht( nachrichtParam, new Text( "Fehler" ), new Text( "Die Nachricht konnte nicht gesendet werden." ), new Text( "Ok" ), 0 );
			else
			{
				nachricht->setAuswahl( 0, 0 );
				nachricht->setText( "" );
			}
			delete[] bytes;
		}
	}
}

bool StatistikChat::tick( double tickVal )
{
	bool rend = verlauf->tick( tickVal );
	rend |= nachricht->tick( tickVal );
	rend |= senden->tick( tickVal );
	rend |= verlassen->tick( tickVal );
	rend |= spielerListe->tick( tickVal );
	return rend;
}

void StatistikChat::render( Bild &zRObj )
{
	verlauf->render( zRObj );
	nachricht->render( zRObj );
	senden->render( zRObj );
	verlassen->render( zRObj );
	spielerListe->render( zRObj );
}

// constant
bool StatistikChat::hatVerlassen()
{
	return beenden;
}

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

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