// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; see the file COPYING.LIB.  If not, write to
// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
// Boston, MA 02110-1301, USA.

#include <iostream>

#include <tqdom.h>
#include <tqtextcodec.h>
#include <tqtextstream.h>
#include <tqtimer.h>

#include <kdebug.h>
#include <tdelocale.h>

#include <atlantic_core.h>
#include <auction.h>
#include <configoption.h>
#include <estate.h>
#include <estategroup.h>
#include <game.h>
#include <player.h>
#include <trade.h>

#include "atlantik_network.h"

AtlantikNetwork::AtlantikNetwork(AtlanticCore *atlanticCore) : KExtendedSocket(0, 0, KExtendedSocket::inputBufferedSocket)
{
	m_atlanticCore = atlanticCore;
	m_textStream = new TQTextStream(this);
	m_textStream->setCodec(TQTextCodec::codecForName("utf8"));
	m_playerId = -1;
	m_serverVersion = "";

	TQObject::connect(this, TQ_SIGNAL(readyRead()), this, TQ_SLOT(slotRead()));
	TQObject::connect(this, TQ_SIGNAL(lookupFinished(int)),
	                 this, TQ_SLOT(slotLookupFinished(int)));
	TQObject::connect(this, TQ_SIGNAL(connectionSuccess()),
	                 this, TQ_SLOT(slotConnectionSuccess()));
	TQObject::connect(this, TQ_SIGNAL(connectionFailed(int)),
	                 this, TQ_SLOT(slotConnectionFailed(int)));
}

AtlantikNetwork::~AtlantikNetwork(void)
{
	delete m_textStream;
}

void AtlantikNetwork::rollDice()
{
	writeData(".r");
}

void AtlantikNetwork::buyEstate()
{
	writeData(".eb");
}

void AtlantikNetwork::auctionEstate()
{
	writeData(".ea");
}

void AtlantikNetwork::startGame()
{
	writeData(".gs");
}

void AtlantikNetwork::reconnect(const TQString &cookie)
{
	writeData(".R" + cookie);
}

void AtlantikNetwork::leaveGame()
{
	writeData(".gx");
}

void AtlantikNetwork::endTurn()
{
	writeData(".E");
}

void AtlantikNetwork::setName(TQString name)
{
	// Almost deprecated, will be replaced by libmonopdprotocol
	writeData(TQString(".n%1").arg(name));
}

void AtlantikNetwork::tokenConfirmation(Estate *estate)
{
	writeData(TQString(".t%1").arg(estate ? estate->id() : -1));
}

void AtlantikNetwork::estateToggleMortgage(Estate *estate)
{
	writeData(TQString(".em%1").arg(estate ? estate->id() : -1));
}

void AtlantikNetwork::estateHouseBuy(Estate *estate)
{
	writeData(TQString(".hb%1").arg(estate ? estate->id() : -1));
}

void AtlantikNetwork::estateHouseSell(Estate *estate)
{
	writeData(TQString(".hs%1").arg(estate ? estate->id() : -1));
}

void AtlantikNetwork::newGame(const TQString &gameType)
{
	writeData(TQString(".gn%1").arg(gameType));
}

void AtlantikNetwork::joinGame(int gameId)
{
	writeData(TQString(".gj%1").arg(gameId));
}

void AtlantikNetwork::cmdChat(TQString msg)
{
	writeData(msg);
}

void AtlantikNetwork::newTrade(Player *player)
{
	writeData(TQString(".Tn%1").arg(player ? player->id() : -1));
}

void AtlantikNetwork::kickPlayer(Player *player)
{
	writeData(TQString(".gk%1").arg(player ? player->id() : -1));
}

void AtlantikNetwork::tradeUpdateEstate(Trade *trade, Estate *estate, Player *player)
{
	writeData(TQString(".Te%1:%2:%3").arg(trade ? trade->tradeId() : -1).arg(estate ? estate->id() : -1).arg(player ? player->id() : -1));
}

void AtlantikNetwork::tradeUpdateMoney(Trade *trade, unsigned int money, Player *pFrom, Player *pTo)
{
	writeData(TQString(".Tm%1:%2:%3:%4").arg(trade ? trade->tradeId() : -1).arg(pFrom ? pFrom->id() : -1).arg(pTo ? pTo->id() : -1).arg(money));
}

void AtlantikNetwork::tradeReject(Trade *trade)
{
	writeData(TQString(".Tr%1").arg(trade ? trade->tradeId() : -1));
}

void AtlantikNetwork::tradeAccept(Trade *trade)
{
	writeData(TQString(".Ta%1:%2").arg(trade ? trade->tradeId() : -1).arg(trade ? trade->revision() : -1));
}

void AtlantikNetwork::auctionBid(Auction *auction, int amount)
{
	writeData(TQString(".ab%1:%2").arg(auction ? auction->auctionId() : -1).arg(amount));
}

void AtlantikNetwork::setImage(const TQString &name)
{
	writeData(TQString(".pi%1").arg(name));
}

void AtlantikNetwork::jailPay()
{
	writeData(".jp");
}

void AtlantikNetwork::jailRoll()
{
	writeData(".jr");
}

void AtlantikNetwork::jailCard()
{
	writeData(".jc");
}

void AtlantikNetwork::changeOption(int configId, const TQString &value)
{
	writeData( TQString(".gc%1:%2").arg(configId).arg(value) );
}

void AtlantikNetwork::writeData(TQString msg)
{
	emit networkEvent(msg, "1rightarrow");
	msg.append("\n");
	if (socketStatus() == KExtendedSocket::connected)
		*m_textStream << msg;
	else
		kdDebug() << "warning: socket not connected!" << endl;
}

void AtlantikNetwork::slotRead()
{
	if ( socketStatus() != KExtendedSocket::connected )
		return;

	if (canReadLine())
	{
		processMsg(m_textStream->readLine());
		// There might be more data
		TQTimer::singleShot(0, this, TQ_SLOT(slotRead()));
	}
	else
	{
		// Maximum message size. Messages won't get bigger than 32k anyway, so
		// if we didn't receive a newline by now, we probably won't anyway.
		if (bytesAvailable() > (1024 * 32))
			flush();
	}
}

void AtlantikNetwork::processMsg(const TQString &msg)
{
	emit networkEvent(msg, "1leftarrow");

	TQDomDocument dom;
	dom.setContent(msg);
	TQDomElement e = dom.documentElement();
	if (e.tagName() != "monopd")
	{
		// Invalid data, request full update from server
		writeData(".f");
		return;
	}
	TQDomNode n = e.firstChild();
	processNode(n);
	m_atlanticCore->printDebug();
}

void AtlantikNetwork::processNode(TQDomNode n)
{
	TQDomAttr a;

	for ( ; !n.isNull() ; n = n.nextSibling() )
	{
		TQDomElement e = n.toElement();
		if(!e.isNull())
		{
			if (e.tagName() == "server")
			{
				a = e.attributeNode( TQString("version") );
				if ( !a.isNull() )
					m_serverVersion = a.value();

				emit receivedHandshake();
			}
			else if (e.tagName() == "msg")
			{
				a = e.attributeNode(TQString("type"));
				if (!a.isNull())
				{
					if (a.value() == "error")
						emit msgError(e.attributeNode(TQString("value")).value());
					else if (a.value() == "info")
						emit msgInfo(e.attributeNode(TQString("value")).value());
					else if (a.value() == "chat")
						emit msgChat(e.attributeNode(TQString("author")).value(), e.attributeNode(TQString("value")).value());
				}
			}
			else if (e.tagName() == "display")
			{
				int estateId = -1;

				a = e.attributeNode(TQString("estateid"));
				if (!a.isNull())
				{
					estateId = a.value().toInt();
					Estate *estate;
					estate = m_atlanticCore->findEstate(a.value().toInt());

					emit displayDetails(e.attributeNode(TQString("text")).value(), e.attributeNode(TQString("cleartext")).value().toInt(), e.attributeNode(TQString("clearbuttons")).value().toInt(), estate);

					bool hasButtons = false;
					for( TQDomNode nButtons = n.firstChild() ; !nButtons.isNull() ; nButtons = nButtons.nextSibling() )
					{
						TQDomElement eButton = nButtons.toElement();
						if (!eButton.isNull() && eButton.tagName() == "button")
						{
							emit addCommandButton(eButton.attributeNode(TQString("command")).value(), eButton.attributeNode(TQString("caption")).value(), eButton.attributeNode(TQString("enabled")).value().toInt());
							hasButtons = true;
						}
					}

					if (!hasButtons)
						emit addCloseButton();
				}
			}
			else if (e.tagName() == "client")
			{
				a = e.attributeNode(TQString("playerid"));
				if (!a.isNull())
					m_playerId = a.value().toInt();

				a = e.attributeNode(TQString("cookie"));
				if (!a.isNull())
					emit clientCookie(a.value());
			}
			else if (e.tagName() == "configupdate")
			{
				int configId = -1;
				a = e.attributeNode(TQString("configid"));
				if (!a.isNull())
				{
					configId = a.value().toInt();
					ConfigOption *configOption;
					if (!(configOption = m_atlanticCore->findConfigOption(configId)))
						configOption = m_atlanticCore->newConfigOption( configId );

					a = e.attributeNode(TQString("name"));
					if (configOption && !a.isNull())
						configOption->setName(a.value());

					a = e.attributeNode(TQString("description"));
					if (configOption && !a.isNull())
						configOption->setDescription(a.value());

					a = e.attributeNode(TQString("edit"));
					if (configOption && !a.isNull())
						configOption->setEdit(a.value().toInt());

					a = e.attributeNode(TQString("value"));
					if (configOption && !a.isNull())
						configOption->setValue(a.value());

					if (configOption)
						configOption->update();
				}

				int gameId = -1;
				a = e.attributeNode(TQString("gameid"));
				if (!a.isNull())
				{
					gameId = a.value().toInt();
					for( TQDomNode nOptions = n.firstChild() ; !nOptions.isNull() ; nOptions = nOptions.nextSibling() )
					{
						TQDomElement eOption = nOptions.toElement();
						if (!eOption.isNull() && eOption.tagName() == "option")
							emit gameOption(eOption.attributeNode(TQString("title")).value(), eOption.attributeNode(TQString("type")).value(), eOption.attributeNode(TQString("value")).value(), eOption.attributeNode(TQString("edit")).value(), eOption.attributeNode(TQString("command")).value());
					}
					emit endConfigUpdate();
				}
			}
			else if (e.tagName() == "deletegame")
			{
				a = e.attributeNode(TQString("gameid"));
				if (!a.isNull())
				{
					int gameId = a.value().toInt();

					Game *game = m_atlanticCore->findGame(gameId);
					if (game)
						m_atlanticCore->removeGame(game);
				}
			}
			else if (e.tagName() == "gameupdate")
			{
				int gameId = -1;

				a = e.attributeNode(TQString("gameid"));
				if (!a.isNull())
				{
					gameId = a.value().toInt();

					Player *playerSelf = m_atlanticCore->playerSelf();
					if ( playerSelf && playerSelf->game() )
						kdDebug() << "gameupdate for " << TQString::number(gameId) << " with playerSelf in game " << TQString::number(playerSelf->game()->id()) << endl;
					else
						kdDebug() << "gameupdate for " << TQString::number(gameId) << endl;


					Game *game = 0;
					if (gameId == -1)
					{
						a = e.attributeNode(TQString("gametype"));
						if ( !a.isNull() && !(game = m_atlanticCore->findGame(a.value())) )
							game = m_atlanticCore->newGame(gameId, a.value());
					}
					else if (!(game = m_atlanticCore->findGame(gameId)))
						game = m_atlanticCore->newGame(gameId);

					a = e.attributeNode(TQString("canbejoined"));
					if (game && !a.isNull())
						game->setCanBeJoined(a.value().toInt());

					a = e.attributeNode(TQString("description"));
					if (game && !a.isNull())
						game->setDescription(a.value());

					a = e.attributeNode(TQString("name"));
					if (game && !a.isNull())
						game->setName(a.value());

					a = e.attributeNode(TQString("players"));
					if (game && !a.isNull())
						game->setPlayers(a.value().toInt());

					a = e.attributeNode(TQString("master"));
					if (game && !a.isNull())
					{
						// Ensure setMaster succeeds by creating player if necessary
						Player *player = m_atlanticCore->findPlayer( a.value().toInt() );
						if ( !player )
							player = m_atlanticCore->newPlayer( a.value().toInt() );
						game->setMaster( player );
					}

					TQString status = e.attributeNode(TQString("status")).value();
					if ( m_serverVersion.left(4) == "0.9." || (playerSelf && playerSelf->game() == game) )
					{
						if (status == "config")
							emit gameConfig();
						else if (status == "init")
							emit gameInit();
						else if (status == "run")
							emit gameRun();
						else if (status == "end")
							emit gameEnd();
					}

					if (game)
						game->update();
				}
			}
			else if (e.tagName() == "deleteplayer")
			{
				a = e.attributeNode(TQString("playerid"));
				if (!a.isNull())
				{
					int playerId = a.value().toInt();

					Player *player = m_atlanticCore->findPlayer(playerId);
					if (player)
						m_atlanticCore->removePlayer(player);
				}
			}
			else if (e.tagName() == "playerupdate")
			{
				int playerId = -1;

				a = e.attributeNode(TQString("playerid"));
				if (!a.isNull())
				{
					playerId = a.value().toInt();

					Player *player;
					if (!(player = m_atlanticCore->findPlayer(playerId)))
						player = m_atlanticCore->newPlayer( playerId, (m_playerId == playerId) );

					// Update player name
					a = e.attributeNode(TQString("name"));
					if (player && !a.isNull())
						player->setName(a.value());

					// Update player game
					a = e.attributeNode(TQString("game"));
					if (player && !a.isNull())
					{
						int gameId = a.value().toInt();
						if (gameId == -1)
							player->setGame( 0 );
						else
						{
							// Ensure setGame succeeds by creating game if necessary
							Game *game = m_atlanticCore->findGame(a.value().toInt());
							if (!game)
								game = m_atlanticCore->newGame(a.value().toInt()); // 
							player->setGame( game );
						}
					}

					// Update player host
					a = e.attributeNode(TQString("host"));
					if (player && !a.isNull())
						player->setHost(a.value());

					// Update player image/token
					a = e.attributeNode(TQString("image"));
					if (player && !a.isNull())
						player->setImage(a.value());

					// Update player money
					a = e.attributeNode(TQString("money"));
					if (player && !a.isNull())
						player->setMoney(a.value().toInt());

					a = e.attributeNode(TQString("bankrupt"));
					if (player && !a.isNull())
						player->setBankrupt(a.value().toInt());

					a = e.attributeNode(TQString("hasdebt"));
					if (player && !a.isNull())
						player->setHasDebt(a.value().toInt());

					a = e.attributeNode(TQString("hasturn"));
					if (player && !a.isNull())
						player->setHasTurn(a.value().toInt());

					// Update whether player can roll
					a = e.attributeNode(TQString("can_roll"));
					if (player && !a.isNull())
						player->setCanRoll(a.value().toInt());

					// Update whether player can buy
					a = e.attributeNode(TQString("can_buyestate"));
					if (player && !a.isNull())
						player->setCanBuy(a.value().toInt());

					// Update whether player can auction
					a = e.attributeNode(TQString("canauction"));
					if (player && !a.isNull())
						player->setCanAuction(a.value().toInt());

					// Update whether player can use a card
					a = e.attributeNode(TQString("canusecard"));
					if (player && !a.isNull())
						player->setCanUseCard(a.value().toInt());

					// Update whether player is jailed
					a = e.attributeNode(TQString("jailed"));
					if (player && !a.isNull())
					{
						player->setInJail(a.value().toInt());
						// TODO: emit signal with player ptr so board can setText and display something
					}

					// Update player location
					a = e.attributeNode(TQString("location"));
					if (!a.isNull())
					{
						m_playerLocationMap[player] = a.value().toInt();

						bool directMove = false;

						Estate *estate = m_atlanticCore->findEstate(a.value().toInt());

						a = e.attributeNode(TQString("directmove"));
						if (!a.isNull())
							directMove = a.value().toInt();

						if (player && estate)
						{
							if (directMove)
								player->setLocation(estate);
							else
								player->setDestination(estate);
						}
					}

					if (player)
						player->update();
				}
			}
			else if (e.tagName() == "estategroupupdate")
			{
				a = e.attributeNode(TQString("groupid"));
				if (!a.isNull())
				{
					int groupId = a.value().toInt();

					EstateGroup *estateGroup = 0;
					bool b_newEstateGroup = false;
					
					if (!(estateGroup = m_atlanticCore->findEstateGroup(groupId)))
					{
						// Create EstateGroup object
						estateGroup = m_atlanticCore->newEstateGroup(a.value().toInt());
						b_newEstateGroup = true;
					}

					a = e.attributeNode(TQString("name"));
					if (estateGroup && !a.isNull())
						estateGroup->setName(a.value());

					// Emit signal so GUI implementations can create view(s)
					// TODO:  port to atlanticcore and create view there
					if (estateGroup)
					{
						if (b_newEstateGroup)
							emit newEstateGroup(estateGroup);
						estateGroup->update();
					}
				}
			}
			else if (e.tagName() == "estateupdate")
			{
				int estateId = -1;

				a = e.attributeNode(TQString("estateid"));
				if (!a.isNull())
				{
					estateId = a.value().toInt();
					
					Estate *estate = 0;
					bool b_newEstate = false;

					// FIXME: allow any estateId, GUI should not use it to determin its geometry
					if (estateId >= 0 && estateId < 100 && !(estate = m_atlanticCore->findEstate(a.value().toInt())))
					{
						// Create estate object
						estate = m_atlanticCore->newEstate(estateId);
						b_newEstate = true;

						TQObject::connect(estate, TQ_SIGNAL(estateToggleMortgage(Estate *)), this, TQ_SLOT(estateToggleMortgage(Estate *)));
						TQObject::connect(estate, TQ_SIGNAL(estateHouseBuy(Estate *)), this, TQ_SLOT(estateHouseBuy(Estate *)));
						TQObject::connect(estate, TQ_SIGNAL(estateHouseSell(Estate *)), this, TQ_SLOT(estateHouseSell(Estate *)));
						TQObject::connect(estate, TQ_SIGNAL(newTrade(Player *)), this, TQ_SLOT(newTrade(Player *)));

						// Players without estate should get one
						Player *player = 0;
						TQPtrList<Player> playerList = m_atlanticCore->players();
						for (TQPtrListIterator<Player> it(playerList); (player = *it) ; ++it)
							if (m_playerLocationMap[player] == estate->id())
								player->setLocation(estate);
					}

					a = e.attributeNode(TQString("name"));
					if (estate && !a.isNull())
						estate->setName(a.value());

					a = e.attributeNode(TQString("color"));
					if (estate && !a.isNull() && !a.value().isEmpty())
						estate->setColor(a.value());

					a = e.attributeNode(TQString("bgcolor"));
					if (estate && !a.isNull())
						estate->setBgColor(a.value());

					a = e.attributeNode(TQString("owner"));
					Player *player = m_atlanticCore->findPlayer(a.value().toInt());
					if (estate && !a.isNull())
						estate->setOwner(player);

					a = e.attributeNode(TQString("houses"));
					if (estate && !a.isNull())
						estate->setHouses(a.value().toInt());

					a = e.attributeNode(TQString("mortgaged"));
					if (estate && !a.isNull())
						estate->setIsMortgaged(a.value().toInt());

					a = e.attributeNode(TQString("group"));
					if (!a.isNull())
					{
						EstateGroup *estateGroup = m_atlanticCore->findEstateGroup(a.value().toInt());
						if (estate)
							estate->setEstateGroup(estateGroup);
					}

					a = e.attributeNode(TQString("can_toggle_mortgage"));
					if (estate && !a.isNull())
						estate->setCanToggleMortgage(a.value().toInt());

					a = e.attributeNode(TQString("can_be_owned"));
					if (estate && !a.isNull())
						estate->setCanBeOwned(a.value().toInt());

					a = e.attributeNode(TQString("can_buy_houses"));
					if (estate && !a.isNull())
						estate->setCanBuyHouses(a.value().toInt());

					a = e.attributeNode(TQString("can_sell_houses"));
					if (estate && !a.isNull())
						estate->setCanSellHouses(a.value().toInt());

					a = e.attributeNode(TQString("price"));
					if (estate && !a.isNull())
						estate->setPrice(a.value().toInt());

					a = e.attributeNode(TQString("houseprice"));
        				if (estate && !a.isNull())
                				estate->setHousePrice(a.value().toInt());

        				a = e.attributeNode(TQString("sellhouseprice"));
        				if (estate && !a.isNull())
                				estate->setHouseSellPrice(a.value().toInt());
						
					a = e.attributeNode(TQString("mortgageprice"));
        				if (estate && !a.isNull())
                				estate->setMortgagePrice(a.value().toInt());

        				a = e.attributeNode(TQString("unmortgageprice"));
        				if (estate && !a.isNull())
                				estate->setUnmortgagePrice(a.value().toInt());
						
					a = e.attributeNode(TQString("money"));
					if (estate && !a.isNull())
						estate->setMoney(a.value().toInt());

					// Emit signal so GUI implementations can create view(s)
					// TODO:  port to atlanticcore and create view there
					if (estate)
					{
						if (b_newEstate)
							emit newEstate(estate);
						estate->update();
					}
				}
			}
			else if (e.tagName() == "tradeupdate")
			{
				a = e.attributeNode(TQString("tradeid"));
				if (!a.isNull())
				{
					int tradeId = a.value().toInt();

					Trade *trade = m_atlanticCore->findTrade(tradeId);
					if (!trade)
					{
						// Create trade object
						trade = m_atlanticCore->newTrade(tradeId);

						TQObject::connect(trade, TQ_SIGNAL(updateEstate(Trade *, Estate *, Player *)), this, TQ_SLOT(tradeUpdateEstate(Trade *, Estate *, Player *)));
						TQObject::connect(trade, TQ_SIGNAL(updateMoney(Trade *, unsigned int, Player *, Player *)), this, TQ_SLOT(tradeUpdateMoney(Trade *, unsigned int, Player *, Player *)));
						TQObject::connect(trade, TQ_SIGNAL(reject(Trade *)), this, TQ_SLOT(tradeReject(Trade *)));
						TQObject::connect(trade, TQ_SIGNAL(accept(Trade *)), this, TQ_SLOT(tradeAccept(Trade *)));
					}

					a = e.attributeNode(TQString("revision"));
					if (trade && !a.isNull())
						trade->setRevision(a.value().toInt());

					TQString type = e.attributeNode(TQString("type")).value();
					if (type=="new")
					{
						// TODO: trade->setActor
						// Player *player = m_atlanticCore->findPlayer(e.attributeNode(TQString("actor")).value().toInt());
						// if (trade && player)
						// 	trade->setActor(player);

						TQDomNode n_player = n.firstChild();
						while(!n_player.isNull())
						{
							TQDomElement e_player = n_player.toElement();
							if (!e_player.isNull() && e_player.tagName() == "tradeplayer")
							{
								Player *player = m_atlanticCore->findPlayer(e_player.attributeNode(TQString("playerid")).value().toInt());
								if (trade && player)
								{
									trade->addPlayer(player);
									TQObject::connect(m_atlanticCore, TQ_SIGNAL(removePlayer(Player *)), trade, TQ_SLOT(removePlayer(Player *)));
								}
							}
							n_player = n_player.nextSibling();
						}
					}
					else if (type=="accepted" && trade)
						emit msgTradeUpdateAccepted(trade);
					else if (type=="completed" && trade)
					{
						m_atlanticCore->removeTrade(trade);
						trade = 0;
					}
					else if (type=="rejected")
					{
						Player *player = m_atlanticCore->findPlayer(e.attributeNode(TQString("actor")).value().toInt());
						if (trade)
							trade->reject(player);
						if ( player && player == m_atlanticCore->playerSelf() )
						{
							m_atlanticCore->removeTrade(trade);
							trade = 0;
						}
					}
					else
					{
						// No type specified, edit is implied.

						TQDomNode n_child = n.firstChild();
						while(!n_child.isNull())
						{
							TQDomElement e_child = n_child.toElement();
							if (!e_child.isNull())
							{
								if (e_child.tagName() == "tradeplayer")
								{
									a = e_child.attributeNode(TQString("playerid"));
									if (!a.isNull())
									{
										Player *player = m_atlanticCore->findPlayer(a.value().toInt());

										a = e_child.attributeNode(TQString("accept"));
										if (trade && player && !a.isNull())
											trade->updateAccept(player, (bool)(a.value().toInt()));
									}
								}
								else if (e_child.tagName() == "tradeestate")
								{
									a = e_child.attributeNode(TQString("estateid"));
									if (!a.isNull())
									{
										Estate *estate = m_atlanticCore->findEstate(a.value().toInt());
										a = e_child.attributeNode(TQString("targetplayer"));
										if (!a.isNull())
										{
											Player *player = m_atlanticCore->findPlayer(a.value().toInt());
											// Allow NULL player, it will remove the component
											if (trade && estate)
												trade->updateEstate(estate, player);
										}
									}
								}
								else if (e_child.tagName() == "trademoney")
								{
									Player *pFrom = 0, *pTo = 0;

									a = e_child.attributeNode(TQString("playerfrom"));
									if (!a.isNull())
										pFrom = m_atlanticCore->findPlayer(a.value().toInt());

									a = e_child.attributeNode(TQString("playerto"));
									if (!a.isNull())
										pTo = m_atlanticCore->findPlayer(a.value().toInt());

									a = e_child.attributeNode(TQString("money"));
									kdDebug() << "tradeupdatemoney" << (pFrom ? "1" : "0") << (pTo ? "1" : "0") << (a.isNull() ? "0" : "1") << endl;
									if (trade && pFrom && pTo && !a.isNull())
										trade->updateMoney(a.value().toInt(), pFrom, pTo);
								}
							}
							n_child = n_child.nextSibling();
						}
					}

					if (trade)
						trade->update();
				}
			}
			else if (e.tagName() == "auctionupdate")
			{
				a = e.attributeNode(TQString("auctionid"));
				if (!a.isNull())
				{
					int auctionId = a.value().toInt();

					Auction *auction;
					bool b_newAuction = false;
					if (!(auction = m_auctions[auctionId]))
					{
						// Create auction object
						auction = m_atlanticCore->newAuction(auctionId, m_atlanticCore->findEstate(e.attributeNode(TQString("estateid")).value().toInt()));
						m_auctions[auctionId] = auction;

						TQObject::connect(auction, TQ_SIGNAL(bid(Auction *, int)), this, TQ_SLOT(auctionBid(Auction *, int)));

						b_newAuction = true;
					}

					a = e.attributeNode(TQString("highbidder"));
					if (!a.isNull())
					{
						Player *player = m_atlanticCore->findPlayer(e.attributeNode(TQString("highbidder")).value().toInt());
						a = e.attributeNode(TQString("highbid"));
						if (auction && !a.isNull())
							auction->newBid(player, a.value().toInt());
					}

					a = e.attributeNode(TQString("status"));
					if (auction && !a.isNull())
					{
						int status = a.value().toInt();
						auction->setStatus(status);

						// TODO: find a good way to visualise "sold!"
						if (status == 3)
						{
							m_atlanticCore->delAuction(auction);
							m_auctions[auctionId] = 0;
							auction = 0;
						}
					}

					// Emit signal so GUI implementations can create view(s)
					// TODO:  port to atlanticcore and create view there
					if (auction)
					{
						if (b_newAuction)
							emit newAuction(auction);
						auction->update();
					}
				}
			}
			else
				kdDebug() << "ignored TAG: " << e.tagName() << endl;
		}
		// TODO: remove permanently?
		// TQDomNode node = n.firstChild();
		// processNode(node);
	}
}

void AtlantikNetwork::serverConnect(const TQString host, int port)
{
	setAddress(host, port);
	enableRead(true);
	emit msgStatus(i18n("Connecting to %1:%2...").arg(host).arg(TQString::number(port)), "connect_creating");
	startAsyncConnect();
}

void AtlantikNetwork::slotLookupFinished(int count)
{
	emit msgStatus(i18n("Server host name lookup finished..."));
}

void AtlantikNetwork::slotConnectionSuccess()
{
	emit msgStatus(i18n("Connected to %1:%2.").arg(host()).arg(port()), "connect_established");
}

void AtlantikNetwork::slotConnectionFailed(int error)
{
	emit msgStatus(i18n("Connection failed! Error code: %1").arg(error), "connect_no");
}

#include "atlantik_network.moc"
