/****************************************************************
**
** Attal : Lords of Doom
**
** game.cpp
** Manages the whole game
**
** Version : $Id: game.cpp,v 1.63 2004/12/24 18:28:18 lusum Exp $
**
** Author(s) : Pascal Audoux - Sardi Carlo
**
** Date : 17/08/2000
**
** Licence :
**	This program is free software; you can redistribute it and/or modify
**   	it under the terms of the GNU General Public License as published by
**     	the Free Software Foundation; either version 2, or (at your option)
**      any later version.
**
**	This program 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 General Public License for more details.
**
****************************************************************/

#include "game.h"

// generic include files
#include <assert.h>
// include files for QT
#include <qinputdialog.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qmessagebox.h>
#include <qtabwidget.h>
#include <qhostaddress.h> 
// application specific includes
#include "conf.h"
#include "libCommon/artefactManager.h"
#include "libCommon/attalSocket.h"
#include "libCommon/calendar.h"
#include "libCommon/dataTheme.h"
#include "libCommon/genericEvent.h"
#include "libCommon/genericInsideBuilding.h"
#include "libCommon/pathFinder.h"
#include "libCommon/technic.h"
#include "libCommon/unit.h"
#include "libCommon/priceMarket.h"

#include "libFight/fightUnit.h"

#include "libClient/askChest.h"
#include "libClient/askDialog.h"
#include "libClient/bonus.h"
#include "libClient/building.h"
#include "libClient/chatWidget.h"
#include "libClient/chest.h"
#include "libClient/displayLord.h"
#include "libClient/displayBase.h"
#include "libClient/event.h"
#include "libClient/gainLevel.h"
#include "libClient/gameInfo.h"
#include "libClient/graphicalArtefact.h"
#include "libClient/gui.h"
#include "libClient/imageTheme.h"
#include "libClient/lord.h"
#include "libClient/lordExchange.h"
#include "libClient/mapCreature.h"
#include "libClient/mapView.h"
#include "libClient/ressourceBar.h"


extern QString DATA_PATH;
extern QString IMAGE_PATH;
extern TechnicList techList;
extern DataTheme DataTheme;
extern ImageTheme ImageTheme;

/** add comments here */
Game::Game( QWidget * parent , const char * name )
  : QWidget( parent, name, Qt::WStyle_Customize | Qt::WStyle_DialogBorder ),
	  GameDescription()
{
	_map = new Map( this );
	_isPlaying = false;
	_socket = 0;
	_dispLord = 0;
	_lordExchange = 0;
	_currentCell = 0;

	initWidgets();

	_player = new Player( this, (GenericMap *)_map );
	_resourceBar->setPlayer( _player );
	_control->setPlayer( _player );
	_scrLord->setPlayer(_player);
	_scrBase->setPlayer(_player);
	_scrLord->reinit();
	_scrBase->reinit();

	initLords();

	_control->disableGame();
	_scrLord->setEnabled( false );
	_scrBase->setEnabled( false );
	_control->reinit();

	connect( _chat, SIGNAL( sig_message( QString ) ), SLOT( slot_message( QString ) ) );
	connect( _scrLord, SIGNAL( sig_lord() ), SLOT( slot_displayLord() ) );
	connect( _scrBase, SIGNAL( sig_base() ), SLOT( slot_displayBase() ) );
	connect( _scrLord, SIGNAL( sig_lordSelected() ), SLOT( slot_lordSelected() ) );
	connect( _scrBase, SIGNAL( sig_baseSelected() ), SLOT( slot_baseSelected() ) );
	connect( _control, SIGNAL( sig_endTurn() ), SLOT( slot_endTurn() ) );
	//connect( _control, SIGNAL( sig_lord() ), SLOT( slot_displayLord() ) );
	//connect( _control, SIGNAL( sig_base() ), SLOT( slot_displayBase() ) );
	connect( _view , SIGNAL( sig_mouseMoved  ( Cell * ) ), SLOT( slot_mouseMoved  ( Cell * ) ) );
	connect( _view , SIGNAL( sig_mouseLeftPressed( Cell * ) ), SLOT( slot_mouseLeftPressed( Cell * ) ) );
	connect( _view , SIGNAL( sig_mouseRightPressed( Cell * ) ), SLOT( slot_mouseRightPressed( Cell * ) ) );
	connect( _miniMap , SIGNAL( sig_mouseReleasedMinimap( GenericCell * ) ), SLOT( slot_centerMinimap( GenericCell * ) ) );
}

Game::~Game()
{
	delete _control;
	delete _miniMap;
	delete _gameInfo;
	delete _chat;
	delete _view;
	delete _player;
	delete _map;
}

void Game::initWidgets()
{
	_map->resize( 4000, 3000 );
	_view = new MapView( _map, this );
	_control = new GameControl( this );

	QHBoxLayout * layH1 = new QHBoxLayout();
	layH1->addWidget( _view , 1 );
	layH1->addWidget( _control );

	_chat = new ChatWidget( this );

	_gameInfo = new GameInfo( _calendar, this );
	_scrLord = new ScrollLord(this);
	_scrBase = new ScrollBase(this);

	_tab = new QTabWidget( this );
	_tab->insertTab( _gameInfo, tr( "Game Info" ) );
	_tab->insertTab( _scrLord, tr( "Lords" ) );
	_tab->insertTab( _scrBase, tr( "Bases" ) );

	_miniMap = new MiniMap( _map, this );

	QHBoxLayout * layH2 = new QHBoxLayout();
	layH2->addWidget( _chat, 1 );
	layH2->addWidget( _tab, 1 );
	layH2->addWidget( _miniMap );

	_resourceBar = new RessourceBar( this );

	QVBoxLayout * layout = new QVBoxLayout( this );
	layout->addLayout( layH1, 1 );
	layout->addLayout( layH2 );
	layout->addWidget( _resourceBar );
	layout->activate();
}

void Game::setPlayerName( QString name ) {
	_player->setName( name );
}

void Game::slot_mouseMoved( Cell *cell )
{
	QString msg;

	if( cell != _currentCell ) {
		if( cell->getLord() ) {
			msg = tr( "Lord " ) + cell->getLord()->getName();
			emit sig_statusMsg( msg );
			setCursor( waitCursor );
		} else if( cell->getBase() ) { 
			msg = tr( "Base " ) + cell->getBase()->getName() + QString(tr(" - population: %1 ")).arg(cell->getBase()->getPopulation());
			emit sig_statusMsg( msg );
			setCursor( waitCursor );
		} else if( cell->getBuilding() ) {
			msg = cell->getBuilding()->getName();
			emit sig_statusMsg( msg );
			setCursor( waitCursor );
		} else if( cell->getEvent() ) {
			setCursor( waitCursor );
		} else if( cell->getCreature() ) {
			msg = cell->getCreature()->getCreature()->getName();
			emit sig_statusMsg( msg );
			setCursor( waitCursor );
		} else {
			setCursor( arrowCursor );
			emit sig_statusMsg( "" );
		}
	}
}


void Game::slot_mouseLeftPressed( Cell * cell )
{
	if( !_player ) {
		return;
	}

	switch( _state ) {
	case MS_NOTHING:
		handleClickNothing( cell );
		break;
	case MS_LORD:
		handleClickLord( cell );
		break;
	case MS_BASE:
		handleClickBase( cell );
		break;
	case MS_TECHNIC:
		handleClickTechnic( cell );
		break;
	}
}

void Game::setState( MapState state )
{
	_state = state;
}

void Game::handleClickNothing( Cell * cell )
{
	GenericLord * lord = cell->getLord();
	
	if( lord ) {
		if( _player->hasLord( lord ) ) {
			_scrLord->reinit();
			_scrBase->reinit();
			_player->setSelectedLord( lord );
			_view->goToPosition((Cell *) cell);
		}
		return;
	}

	GenericBase * base = cell->getBase();
		
	if( base ) {
		if( _player->hasBase( base ) ) {
			_player->setSelectedBase( base );
			_scrLord->reinit();
			_scrBase->reinit();
			_view->goToPosition((Cell *) cell);
		}
		return;
	}
}

void Game::handleClickLord( Cell * cell )
{
	GenericLord * selectedLord = _player->getSelectedLord();
		
	if( selectedLord && ( cell->getCoeff() >= 0 ) ) {
		if(cell->getLord()){
			_view->goToPosition((Cell *) cell);
		}
		if( ((Lord*)selectedLord)->getDestination() != (GenericCell*)cell ) {
			((Lord*)selectedLord)->computePath( (GenericCell*)cell );
		} else {
			if( selectedLord->getCell()->getBuilding() ) {
				selectedLord->getCell()->getBuilding()->out( selectedLord );
			}
			((Lord*)selectedLord)->followPath( _socket );
		}
	}		
}

void Game::handleClickBase( Cell * cell )
{
	GenericBase * base = cell->getBase();
		
	if( base ) {
		if( _player->hasBase( base ) ) {
			if( base == _player->getSelectedBase() ) {
				emit sig_base( base );
				return;
			} else {
				_player->setSelectedBase( base );
				_scrLord->reinit();
				_scrBase->reinit();
				return;
			}
		} else {
			return;
		}
	}	
	
	handleClickNothing( cell );
}

void Game::handleClickTechnic( Cell * /*cell*/ )
{
	/// XXX: TODO
	logEE( "not yet implemented" );
}


void Game::slot_mouseRightPressed( Cell * cell )
{
	if( !_player ) {
		return;
	}

	GenericLord * lord = cell->getLord();
	
	if( lord ) {
	}
}


void Game::slot_centerMinimap( GenericCell * cell )
{
	_view->goToPosition((Cell *) cell);
}

void Game::enter( GenericLord * /*lord*/, GenericBuilding * /*building*/ )
{
	/// XXX: TODO
	logEE( "not yet implemented" );
}

void Game::enter( GenericLord * lord, GenericBase * base )
{
	base->enter( lord );
	emit sig_base( base );
}

void Game::beginTurn()
{
	_isPlaying = true;
	_calendar->newDay();
	_gameInfo->nothing();
	//_gameInfo->IsPlay();
	_gameInfo->setStatePlayer( true );
	if( _calendar->getDay() == 1 ) {
		_player->newWeek();
	}
	_player->newTurn();
	_state = MS_NOTHING;
}

void Game::playerActive( char num )
{
	_gameInfo->waitPlayer( num );
}

void Game::endTurn()
{
	assert( _socket );
	if( _isPlaying ) {
		if( _player->shouldEnd() ) {
			_socket->sendTurnEnd();
			_isPlaying = false;
			_gameInfo->setStatePlayer( _isPlaying );
		} else {
			QMessageBox msb( "Are you sure ?", "One or more heroes may still move. Are you sure you want to end your turn ?", QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape, 0, this );
			if ( msb.exec() == QMessageBox::Yes ) {
				_socket->sendTurnEnd();
				_isPlaying = false;
				_gameInfo->setStatePlayer( _isPlaying );
			}
		}
	}
}

void Game::beginGame( int nb )
{
	setPlayerNumber( nb );
	_control->enableGame();
	_scrLord->enableGame();
	_scrBase->enableGame();
	ImageTheme.playMusicMap();
}

void Game::endGame()
{
	uint i, j;
	emit sig_endGame();
	_control->disableGame();
	_scrLord->setEnabled( false );
	_scrBase->setEnabled( false );
	_scrLord->deselect();
	_scrBase->deselect();

	for( i = 0; i < (uint) _map->getHeight(); i++ ) {
		for( j = 0; j < (uint) _map->getWidth(); j++ ) {
			if( _map->at( i, j )->getLord() ) {
				Lord * lord = (Lord*)_map->at( i, j )->getLord();
				lord->cleanPath();
				delete lord;
			}
			if( _map->at(i, j)->getBuilding() ) {
				Building * building = (Building*)_map->at( i, j )->getBuilding();
				delete building;
			}
			if( _map->at(i, j)->getBase() )	{
				Base * base = (Base*)_map->at( i, j )->getBase();
				delete base;
			}
			if( _map->at(i, j)->getEvent() ) {
				GenericEvent * event = _map->at( i, j )->getEvent();
				delete event;
				//Artefact * artef = (Artefact*)_map->at( i, j )->getArtefact();
				//delete artef;
			}
			if( _map->at(i, j)->getCreature() ) {
				MapCreature * crea =(MapCreature*)_map->at( i, j )->getCreature();
				delete crea;
			}
		}
	}
	_map->cleanData();
	_player->cleanData();
	_miniMap->redrawMap( _map );
	_calendar->reinit();
	_resourceBar->reinit();
	reInitLords();
	_state = MS_NOTHING;
	if( _dispLord ) {
		delete _dispLord;
		_dispLord = 0;
	}
}

void Game::handleSocket()
{
	switch( _socket->getCla1() ) {
	case SO_MSG:
		socketMsg();
		break;
	case SO_GAME:
		socketGame();
		break;
	case SO_TURN:
		socketTurn();
		break;
	case SO_MODIF:
		socketModif();
		break;
	case SO_QR:
		socketQR();
		break;
	case SO_MVT:
		socketMvt();
		break;
	case SO_TECHNIC:
		break;
	case SO_EXCH:
		socketExchange();
		break;
	case SO_CONNECT:
		socketConnect();
		break;
	case SO_FIGHT:
		socketFight();
		break;
	default:
		logEE( "Unknown socket_class" );
	}
}

void Game::socketMsg()
{
	QString msg;
	uchar len = _socket->readChar();
	for( uint i = 0; i < len; i++ ) {
		msg.ref(i) = _socket->readChar(); /// WINDOWS (was msg[i])
	}
	_chat->newMessage( msg );
}

void Game::slot_message( QString msg )
{
	if( _socket ) {
		_socket->sendMessage( _player->getName() + " : " + msg );
	} else {
		_chat->newMessage( "(Not connected) : " + msg );
	}
}

void Game::socketGame()
{
	switch( _socket->getCla2() ) {
	case C_GAME_BEGIN:
		beginGame( _socket->readChar() );
		/// XXX: clear old stuff if necessary
		break;
	case C_GAME_LOST:
		socketGameLost();
		break;
	case C_GAME_WIN:
		socketGameWin();
		break;
	case C_GAME_END:
		endGame();
		break;
	case C_GAME_INFO:
		socketGameInfo();
		break;
	default:
		logEE( "case not handled" );
		break;
	}
}

void Game::socketGameLost()
{
	int nb = _socket->readChar();
	if( nb == _player->getNum() ) {
		endGame();
	} else {
		QString text;
		text = "Player " + QString::number( nb ) + " has lost.";
		GameMessage msg;
		msg.setCaption( "A player has lost." );
		msg.addText( text );
		msg.addPixmap( ImageTheme.getFlag( nb ) );
		msg.exec();
	}
}

void Game::socketGameWin()
{
	int nb = _socket->readChar();
	if( nb == _player->getNum() ) {
		GameMessage msg;
		msg.addText( "You win !!" );
		msg.exec();
		//endGame();
	} else {
		GameMessage msg;
		msg.addText( "A player has win. You lose" );
		msg.exec();
		//endGame();
	}
}

void Game::socketGameInfo()
{
	switch( _socket->getCla3() ) {
	case C_INFOPLAYER_TEAM: {
			uchar player = _socket->readChar();	
			uchar teamId = _socket->readChar();
			if( getPlayer( player ) ) {
				getPlayer( player )->setTeam( teamId );
			}
		} break;
	case C_INFOPLAYER_NAME:
		break;
	}
}

void Game::socketTurn()
{
	switch( _socket->getCla2() ) {
	case C_TURN_PLAY: {
		uint num = _socket->readChar();
		if( num == _player->getNum() ) {
			beginTurn();
		} else {
			playerActive( num );
		}
		} break;
	case C_TURN_LORD:
		logEE( "Should not happen (Client : SO_TURN/C_TURN_LORD)" );
		break;
	case C_TURN_PLORD:
		logEE( "Should not happen (Client : SO_TURN/C_TURN_PLORD)" );
		break;
	case C_TURN_END:
		logEE( "Should not happen (Client : SO_TURN/C_TURN_END)" );
		break;
	}
}

void Game::socketMvt()
{
	// XXX: not finished at all

	if( _socket->getCla2() == C_MVT_ONE ) {
		uchar lord = _socket->readChar();
		int row = _socket->readInt();
		int col = _socket->readInt();

		Lord * theLord = _realLords[ lord ];
		if( theLord ) {
			if( theLord->getOwner() == _player ) {
				int cost = theLord->computeCostMvt( _map->at( row, col ) );
				if( cost >= 0 ) {
					theLord->decreaseBaseCharac( MOVE, cost );
				}
			}

			theLord->moveTo( _map->at( row, col ) );
			if(_map->at( row, col )->getType() != 0){
				_view->goToPosition((Cell *) _map->at( row, col ));
						
			}
			if( _map->computeMinimalNextCost( theLord ) > theLord->getBaseCharac( MOVE ) ) {
				theLord->setBaseCharac( MOVE, 0 );
			}

			if( _map->at( row, col )->getBuilding() != 0 ) {
				if( _realLords[ lord ]->getOwner() == _player ) {
					enter( _player->getSelectedLord(), _map->at( row, col )->getBuilding() );
				}
			} else if( _map->at( row, col )->getBase() != 0 ) {
				if( theLord->getOwner() == _player ) {
					enter( _player->getSelectedLord(), _map->at( row, col )->getBase() );
				}
			}
		} else {
			logEE( "Try to move a non-existent lord %d to cell (%d, %d)", lord, row, col );
		}
	} else {
		logEE( "Should not happen" );
	}
}

void Game::socketExchange()
{
	switch( _socket->getCla2() ) {
	case C_EXCH_START: {
		uchar idLord1 = _socket->readChar();
		uchar idLord2 = _socket->readChar();
		GenericLord * lord1 = _realLords[ idLord1 ];
		GenericLord * lord2 = _realLords[ idLord2 ];
		LordExchange dial;
		if( ! _lordExchange ) {
			_lordExchange = new LordExchange( this );
		}
		_lordExchange->initSocket( _socket );
		_lordExchange->initLords( lord1, lord2 );
		_lordExchange->exec();
		/// XXX: why deleting and not only clearing ??
		delete _lordExchange;
		_lordExchange = 0;
		} break;
	case C_EXCH_UNIT:
		exchangeUnits();
		break;
	case C_EXCH_ARTEFACT:
		exchangeArtefact();
		break;
	case C_EXCH_BASEUNITCL:
		exchangeBaseUnits();
		break;
	default:
		break;
	}
}

void Game::exchangeUnits()
{
	uchar idLord1 = _socket->readChar();
	uchar idUnit1 = _socket->readChar();
	uchar idLord2 = _socket->readChar();
	uchar idUnit2 = _socket->readChar();
	GenericLord * lord1 = 0;
	GenericLord * lord2 = 0;
	if( idLord1 ) {
		lord1 = (GenericLord * )_realLords[ idLord1 ];
	}
	if( idLord2 ) {
		lord2 = (GenericLord * )_realLords[ idLord2 ];
	}

	/// XXX: check player of lord ?
	if( lord1 && lord2 ) {
		GenericFightUnit * unit1 = lord1->getUnit( idUnit1 );
		GenericFightUnit * unit2 = lord2->getUnit( idUnit2 );

		if( unit1 ) {
			if( unit2 ) {
				if( ( unit1->getRace() == unit2->getRace() ) &&
						unit1->getLevel() == unit2->getLevel() ) {
					unit2->addNumber( unit1->getNumber() );
					lord1->setUnit( idUnit1, 0 );
					delete unit1;
				} else {
					lord1->setUnit( idUnit1, unit2 );
					lord2->setUnit( idUnit2, unit1 );
				}
			} else {
				lord2->setUnit( idUnit2, unit1 );
				lord1->setUnit( idUnit1, 0 );
			}
		}
		if(lord1->getOwner() == _player)
		{
			_player->setSelectedLord(lord1);
		}
		if( _dispLord ) {
			_dispLord->reinit();
		}
		if( _lordExchange ) {
			_lordExchange->reinit();
		}
	}
	emit sig_exchange();
}

void Game::exchangeArtefact()
{
	uchar idLord1 = _socket->readChar();
	int item = _socket->readInt();
	uchar idLord2 = _socket->readChar();
	
	GenericLord * lord1 = 0;
	GenericLord * lord2 = 0;
	
	if( idLord1 ) {
		lord1 = (GenericLord * )_realLords[ idLord1 ];
	}
	if( idLord2 ) {
		lord2 = (GenericLord * )_realLords[ idLord2 ];
	}
	
	if( lord1 && lord2 ) {
		ArtefactManager * manag1 = lord1->getArtefactManager();
		ArtefactManager * manag2 = lord2->getArtefactManager();
		
		GenericLordArtefact * artefact = manag1->getArtefact( item );
		
		manag1->removeArtefact( item );
		manag2->addArtefact( artefact );
		
		if( _lordExchange ) {
			_lordExchange->reinit();
		}
		if( _dispLord ) {
			_dispLord->reinit();
		}
	}
}

void Game::exchangeBaseUnits()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	uchar idUnit1 = _socket->readChar();
	uchar idLord = _socket->readChar();
	uchar idUnit2 = _socket->readChar();
	GenericBase * base = 0;
	GenericLord * lord = 0;
	GenericFightUnit * uni1 = 0;
	GenericFightUnit * uni2 = 0;

	base = (GenericBase *) _map->at( row, col )->getBase();

	if( idLord && idLord<255) {
		lord = (GenericLord * )_realLords[ idLord ];
	}


	if( base ) {
		if( idUnit1 <= MAX_UNIT ) {
			uni1 = base->getUnit( idUnit1);
		}
		if( lord ) {
			if( idUnit2 <= MAX_UNIT ) {
				uni2 = lord->getUnit( idUnit2 );
			}
			if( uni1 && uni2 ) {
				if( uni1->getCreature() != uni2->getCreature() ) {
					lord->setUnit( idUnit2, uni1 );
					base->setUnit( idUnit1, uni2 );
				} else {
					uni2->addNumber( uni1->getNumber() );
					base->setUnit( idUnit1, 0 );
					delete uni1;
				}
			} else if (!uni1) {
					lord->setUnit( idUnit2, 0 );
					base->setUnit( idUnit1, uni2 );
			} else if (!uni2) {
				lord->setUnit( idUnit2, uni1 );
				base->setUnit( idUnit1, 0 );
			}
		} else {
			if(idUnit2<=MAX_UNIT) {
				uni2 = base->getUnit( idUnit2);
			}
			if( uni1 && uni2 ) {
				if( uni1->getCreature() != uni2->getCreature() ) {
					base->setUnit( idUnit2, uni1 );
					base->setUnit( idUnit1, uni2 );
				} else {
					uni1->addNumber( uni2->getNumber() );
					base->setUnit( idUnit2, 0 );
					delete uni2;
				}
			} else {
				base->setUnit( idUnit2, uni1 );
				base->setUnit( idUnit1, 0 );
			}
		}	
	}
	emit sig_exchange();
}



void Game::socketModif()
{
	/// XXX: check number of args below... (?)

	switch( _socket->getCla2() ) {
	case C_MOD_MAP:{
		int h = _socket->readInt();
		int w = _socket->readInt();
		//logDD("h/w %d/%d", h, w );
		_map->newUnknownMap( h, w );
}		break;
	case C_MOD_CELL:
		socketModifCell();
		break;
	case C_MOD_LORD:
		socketModifLord();
		break;
	case C_MOD_PLAYER:
		socketModifPlayer();
		break;
	case C_MOD_BASE:
		socketModifBase();
		break;
	case C_MOD_BUILD:
		socketModifBuilding();
		break;
	case C_MOD_ARTEFACT:
		socketModifArtefact();
		break;
	case C_MOD_CREATURE:
		socketModifCreature();
		break;
	case C_MOD_EVENT:
		socketModifEvent();
		break;
	}
}

void Game::socketModifCell()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	int type = _socket->readInt();
	uchar diversification = _socket->readChar();
	int a4 = _socket->readInt();
	int a5 = _socket->readInt();
	int a6 = _socket->readInt();
	int a7 = _socket->readInt();
//logDD("modif deco %d %d", a6, a7 );
	GenericCell * cell = _map->at( row, col );
	_map->changeCell( row, col, type, a4, a5, a6, a7 );
	cell->setDiversification( diversification );
	_miniMap->redrawCell( cell );
}

void Game::socketModifLord()
{
	switch( _socket->getCla3() ) {
	case C_LORD_VISIT:
		socketModifLordVisit();
		break;
	case C_LORD_NEW:
		socketModifLordNew();
		break;
	case C_LORD_MOVE:
		{
			char lord = _socket->readChar();
			int nb = _socket->readInt();
			_realLords[ lord ]->setBaseCharac( MOVE, nb );
			break;
		}
	case C_LORD_MAXMOVE:
		{
			char lord = _socket->readChar();
			int nb = _socket->readInt();
			_realLords[ lord ]->setBaseCharac( MAXMOVE, nb );
			break;
		}
	case C_LORD_SP:
		{
			char lord = _socket->readChar();
			int nb = _socket->readInt();
			_realLords[ lord ]->setBaseCharac( TECHNICPOINT, nb );
			break;
		}
	case C_LORD_MAXSP:
		{
			char lord = _socket->readChar();
			int nb = _socket->readInt();
			_realLords[ lord ]->setBaseCharac( MAXTECHNICPOINT, nb );
			break;
		}
	case C_LORD_MORALE:
		{
			char lord = _socket->readChar();
			char nb = _socket->readChar();
			_realLords[ lord ]->setBaseCharac( MORALE, nb );
			break;
		}
	case C_LORD_LUCK:
		{
			char lord = _socket->readChar();
			char nb = _socket->readChar();
			_realLords[ lord ]->setBaseCharac( LUCK, nb );
			break;
		}
	case C_LORD_EXP:
		{
			char lord = _socket->readChar();
			int nb = _socket->readInt();
			_realLords[ lord ]->setBaseCharac( EXPERIENCE, nb );
			break;
		}
	case C_LORD_ATT:
		{
			char lord = _socket->readChar();
			char nb = _socket->readChar();
			_realLords[ lord ]->setBaseCharac( ATTACK, nb );
			break;
		}
	case C_LORD_DEF:
		{
			char lord = _socket->readChar();
			char nb = _socket->readChar();
			_realLords[ lord ]->setBaseCharac( DEFENSE, nb );
			break;
		}
	case C_LORD_POW:
		{
			char lord = _socket->readChar();
			char nb = _socket->readChar();
			_realLords[ lord ]->setBaseCharac( POWER, nb );
			break;
		}
	case C_LORD_KNOW:
		{
			char lord = _socket->readChar();
			char nb = _socket->readChar();
			_realLords[ lord ]->setBaseCharac( KNOWLEDGE, nb );
		}
		break;
	case C_LORD_UNIT:
		socketModifLordUnit();
		break;
	case C_LORD_REMOVE:
		socketModifLordRemove();
		break;
	case C_LORD_GARRISON:
		socketModifLordGarrison();
		break;
	case C_LORD_MACHINE:
		socketModifLordMachine();
		break;
	}
}

void Game::socketModifLordVisit()
{
	/// XXX: not finished, we should use 'num' for the player color
	uchar num = _socket->readChar();
	int row = _socket->readInt();
	int col = _socket->readInt();
	uchar id = _socket->readChar();
	uchar present = _socket->readChar();

	Lord * lord;
	if( present == 1 ) {
		if( _realLords[ id ] == 0 ) {
			lord = new Lord( _map );
			lord->setId( id );
			_realLords[ id ] = lord;
		} else {
			lord = _realLords[id];
		}
		lord->setAnimated( true );
		lord->setEnabled( true );
		lord->setSelected( true );
		lord->setActive( true );
		/// XXX: change
		lord->setOwner( getPlayer( num ) );
		lord->moveTo( _map->at( row, col ) );
	} else {
		lord = _realLords[ id ];
		lord->getCell()->setLord(NULL);
		if( lord ) {
			delete lord;
			_realLords[ id ] = 0;
		}
	}
}

void Game::socketModifLordNew()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	uchar id = _socket->readChar();

	Lord * lord;
	if( _realLords[ id ] == 0 ) {
		lord = new Lord( _map );
		lord->setId( id );
		_realLords[ id ] = lord;
	} else {
		lord = _realLords[id];
	}
	lord->setAnimated( true );
	lord->setEnabled( true );
	lord->setSelected( true );
	lord->setActive( true );
	lord->moveTo( _map->at( row, col ) );
	lord->setOwner( _player );
	_player->addLord( lord );
	_scrLord->reinit();
	_scrBase->reinit();
}

void Game::socketModifLordUnit()
{
	uchar id = _socket->readChar();
	uchar num = _socket->readChar();
	uchar race = _socket->readChar();
	uchar level = _socket->readChar();
	int nb = _socket->readInt();
	uchar move = _socket->readChar();
	int health = _socket->readInt();

	GenericFightUnit * uni = 0;
	uni =_realLords[ id ]->getUnit( num );
	if(!uni){
		uni = new GenericFightUnit();
		uni->setCreature( race, level );
		uni->setMove( move );
		uni->setHealth( health );
	}
	if( nb == 0 ){
		if( _realLords[ id ]->countUnits() > 1){
			uni->setNumber( nb );
			delete uni;
			uni = 0;
		}		
	}	else {
		uni->setNumber( nb );
	}

	_realLords[ id ]->setUnit( num, uni );
	if(_dispLord){
		_dispLord->reupdate();
	}
}

void Game::socketModifLordRemove()
{
	int idLord = _socket->readChar();
	Lord * lord = _realLords[ idLord ];
	lord->getCell()->setLord( 0 );
	/// XXX: in fact, _realLords may be different ?
	_realLords[ idLord ] = 0;//(Lord *)DataTheme.lords.at( idLord );
	GenericPlayer * player = lord->getOwner();
	if( player ) {
		player->removeLord( (GenericLord *)lord );
	}
	_scrLord->reinit();
	_scrBase->reinit();
	//XXX: Remove lord from map
	lord->cleanPath();
	delete lord;
	//if( lord ) lord->getOwner()->removeLord( lord );
}

void Game::socketModifLordGarrison()
{
	uchar lord = _socket->readChar();
	uchar state = _socket->readChar();
	_realLords[ lord ]->setVisible( state != 1 );
	_scrLord->reinit();
	_scrBase->reinit();
}

void Game::socketModifLordMachine()
{
	uchar lord = _socket->readChar();
	uchar id = _socket->readChar();
	_realLords[ lord ]->addMachine( id );
}

void Game::socketModifPlayer()
{
	switch( _socket->getCla3() ) {
	case C_PLAY_RESS: {
		uchar ress = _socket->readChar();
		_player->setResource( ress, _socket->readInt() );
		_resourceBar->reinit();}
		break;
	case C_PLAY_PRICE: {
		uchar ress = _socket->readChar();
		uint price = _socket->readInt();
		_player->getPriceMarket()->setResourcePrice( ress, price);
		}
		break;

	}
}

void Game::socketModifBase()
{
	switch( _socket->getCla3() ) {
	case C_BASE_NEW:
		socketModifBaseNew();
		break;
	case C_BASE_OWNER:
		socketModifBaseOwner();
		break;
	case C_BASE_NAME:
		socketModifBaseName();
		break;
	case C_BASE_BUILDING:
		socketModifBaseBuilding();
		break;
	case C_BASE_UNIT:
		socketModifBaseUnit();
		break;
	case C_BASE_POPUL:
		socketModifBasePopulation();
		break;
	}
}

void Game::socketModifBaseNew()
{
	uchar race = _socket->readChar();
	int row = _socket->readInt();
	int col = _socket->readInt();
	int population = _socket->readInt();
	uchar id = _socket->readChar();
	int nb = _socket->readChar();

	Base * base = (Base*)_map->at( row, col )->getBase();
	if( ! base ) {
		base = new Base( _map );
		base->setRace( race );
		base->setPosition( (GenericCell *)_map->at( row, col ));
		base->setPopulation( population );
		_map->computeStoppable( (GenericBase *)base );
		base->setId( id );/// XXX: to inv ??
		for( int i = 0; i < nb; i++ ) {
			base->addForbiddenBuilding( _socket->readChar() );
		}
		base->show();
	}
	/// XXX: update base if already created...
}

void Game::socketModifBaseOwner()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	uchar playerNum = _socket->readChar();
	Base * base = (Base*)_map->at( row, col )->getBase();
	//logDD("own base row %d, col  %d, num %d", row,col,playerNum);

	if( playerNum == _player->getNum() ) {
		_player->addBase( base );
		base->setOwner( _player );
	} else {
		/// XXX: improve management of base of other player
		if( base->getOwner() == _player ) {
			_player->removeBase( (GenericBase*)base );
		}
		base->setOwner( getPlayer( playerNum ) );
	}
	_scrLord->reinit();
	_scrBase->reinit();
}

void Game::socketModifBaseName()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	uint length = _socket->readInt();
	QString name;
	
	for( uint i = 0; i < length; i++ ) {
		name.ref(i) = _socket->readChar();
	}
	
	Base * base = (Base*)_map->at( row, col )->getBase();
	base->setName( name );
}

void Game::socketModifBaseBuilding()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	uchar level = _socket->readChar();
	bool create = (bool)_socket->readChar();

	if( _map->at( row, col )->getBase() ) {
		if( create ) {
			GenericInsideBuilding * building = new GenericInsideBuilding();
			building->setRace( _map->at( row, col )->getBase()->getRace() );
			building->setLevel( level );
			_map->at( row, col )->getBase()->addBuilding( building );
		} else {
			GenericInsideBuilding * building =  _map->at( row, col )->getBase()->getBuildingByType( level );
			_map->at( row, col )->getBase()->removeBuilding( building );
		}
	} else {
		logEE( "Base not found" );
	}
}

void Game::socketModifBaseUnit()
{
	int row = _socket->readInt();
	int col = _socket->readInt();

	if( _map->at( row, col )->getBase() ) {
		Base * base = (Base *)_map->at( row, col )->getBase();
		uchar race = _socket->readChar();
		uchar level = _socket->readChar();
		int number = _socket->readInt();
		Creature * creature = DataTheme.creatures.at( race, level );
		base->addGarrison( creature, number );
	}
}

void Game::socketModifBasePopulation()
{
	int row = _socket->readInt();
	int col = _socket->readInt();
	uint popul = _socket->readInt();
	Base * base = (Base*)_map->at( row, col )->getBase();

	if(base){
		base->setPopulation(popul);	
	}

}

void Game::socketModifBuilding()
{
	switch( _socket->getCla3() ) {
	case C_BUILD_NEW: {
		int row = _socket->readInt();
		int col = _socket->readInt();
		uchar type = _socket->readChar();

		if( _map->at( row, col )->getBuilding() == 0 ) {
			Building * building = new Building( _map );
			building->setType( type );
			building->setPosition( _map->at( row, col ) );
			_map->computeStoppable( (GenericBuilding *)building );
			building->show();
		} // XXX: update building if already created ?
	}
	break;
	case C_BUILD_OWNER: {
		int row = _socket->readInt();
		int col = _socket->readInt();
		char playNum = _socket->readChar();
		//logDD("own build row %d, col  %d, num %d", row,col,playNum);

		Building * build = (Building*)_map->at( row, col )->getBuilding();
		if(  playNum == _player->getNum() ) {
			if( build ) {
				_player->addBuilding( (GenericBuilding *) build );
				build->setOwner( _player );
			}
		} else {
			if( build ) {
				if(build->getOwner() == _player){
					_player->removeBuilding( (GenericBuilding *) build );
				}
				build->setOwner( getPlayer(playNum) );
			}
		}
	}
	}
}

void Game::socketModifArtefact()
{
	switch( _socket->getCla3() ) {
		case C_ART_DELLORD: {
			uint type = _socket->readInt();
			char lord = _socket->readChar();
			getLord( lord )->getArtefactManager()->removeArtefactByType( type );
		}
		break;
		case C_ART_ADDLORD: {
			ImageTheme.playSound( AttalSound::SND_GOOD );
			uint type = _socket->readInt();
			char lord = _socket->readChar();
			if( ! getLord( lord )->getArtefactManager()->hasArtefactType( type ) ) {
				getLord( lord )->getArtefactManager()->addArtefact( type );
			}
		}
		break;
	}
}

void Game::socketModifCreature()
{
	switch( _socket->getCla3() ) {
	case C_CRE_NEW: {
		int row = _socket->readInt();
		int col = _socket->readInt();
		uchar race = _socket->readChar();
		uchar level = _socket->readChar();
		int nb = _socket->readInt();
		bool looking = (bool) _socket->readChar();
		MapCreature * creature = new MapCreature( _map );
		creature->setCreature( race, level );
		creature->setCategoryNumber( nb );
		creature->setCell( _map->at( row, col ) );
		creature->setLookingRight( looking );
		_map->at( row, col )->setCreature( creature );
		}
		break;
	case C_CRE_UPDATE: {
		int row = _socket->readInt();
		int col = _socket->readInt();
		int nb = _socket->readInt();
		MapCreature * creature = (MapCreature * ) _map->at( row, col )->getCreature();
		if( creature ) {
			creature->setCategoryNumber( nb );
		}
		}
		break;
	case C_CRE_DEL: {
		int row = _socket->readInt();
		int col = _socket->readInt();
		GenericMapCreature * crea = _map->at( row, col )->getCreature();
		if( crea ) {
			delete crea;
			_map->at( row, col )->setCreature( 0 );
		}
		}
		break;
	}
}

void Game::socketModifEvent()
{
	switch( _socket->getCla3() ) {
	case C_EVENT_NEW:
		socketNewEvent();
		break;
	case C_EVENT_DEL: {
		int row = _socket->readInt();
		int col = _socket->readInt();
		GenericEvent * event = _map->at( row, col )->getEvent();
		if( event ) {
			delete event;
			_map->at( row, col )->setEvent( 0 );
		}
		}
		break;
	}
}

void Game::socketNewEvent()
{
	uint i;
	int row = _socket->readInt();
	int col = _socket->readInt();
	GenericEvent::EventType type = (GenericEvent::EventType) _socket->readChar();

	Event * event = new Event();

	if( type == GenericEvent::EventArtefact ) {
		int id = _socket->readInt();
		uchar typeArtefact = _socket->readChar();

		Artefact * artefact = new Artefact( _map );
		event->setArtefact( (GenericArtefact *)artefact );
		artefact->setId( id );
		artefact->setType( typeArtefact );
	} else if( type == GenericEvent::EventBonus ) {
		uchar typeBonus = _socket->readChar();
		uchar nbParam = _socket->readChar();

		Bonus * bonus = new Bonus( _map );
		event->setBonus( (GenericBonus *)bonus );
		bonus->setType( (GenericBonus::BonusType) typeBonus );
		for( i = 0; i < nbParam; i++ ) {
			bonus->addParam( _socket->readInt() );
		}
		bonus->setupBonus();
	} else if( type == GenericEvent::EventChest ) {
		uchar nbParam = _socket->readChar();

		Chest * chest = new Chest( _map );
		event->setChest( (GenericChest *)chest );
		for( i = 0; i < nbParam; i++ ) {
			chest->addParam( _socket->readInt() );
		}
		chest->setupChest();
	}

	event->setCell( _map->at( row, col ) );
	_map->at( row, col )->setEvent( (GenericEvent*)event );
}

void Game::socketConnect()
{
	uchar tmp;

	switch( _socket->getCla2() ) {
	case C_CONN_OK:
		_socket->sendConnectionName( _player->getName() );
		_chat->newMessage( QString( "Connection established, %1" ).arg( _player->getName() ) );
		_chat->newMessage( QString( "Host address %1" ).arg( _socket->peerAddress().toString()));
		_chat->newMessage( QString( "Host port %1," ).arg( _socket->peerPort())+ QString( " Our port %1" ).arg( _socket->port()));
		break;
	case C_CONN_ID:
		{
			tmp=_socket->readChar();
			_player->setNum( tmp );
			_chat->newMessage( QString( "Connection ID, %1" ).arg( _player->getNum() ) );
		}
		break;
	case C_CONN_NAME:
		{
			QString res;
			uint len = _socket->readChar();
			for( uint i = 0; i < len; i++) {
				res.append( _socket->readChar() );
			}
			_player->setName(res);
			_chat->newMessage( QString( "Name of player: %1" ).arg( res ) );
		}
		break;
	case C_CONN_PLAYER:
		break;
	}
}

/*!

*/

void Game::slot_lordSelected()
{
		_view->goToPosition((Cell *) _player->getSelectedLord()->getCell());
		_scrBase->deselect();
}
	

void Game::slot_baseSelected()
{
		_view->goToPosition((Cell *) _player->getSelectedBase()->getCell());
		_scrLord->deselect();
}

void Game::slot_displayLord()
{
	_view->goToPosition((Cell *) _player->getSelectedLord()->getCell());
	if( _player->numLord() > 0 ) {
		if( _dispLord == 0 ) {
			_dispLord = new DisplayLord( _player, this );
			_dispLord->initSocket(_socket);
		}
		_dispLord->show();
	}
}

void Game::slot_displayBase()
{
	if(_player->getSelectedBase()){
		_view->goToPosition((Cell *) _player->getSelectedBase()->getCell());
		emit sig_base( _player->getSelectedBase() );
	}
}

void Game::socketQR()
{
	switch( _socket->getCla2() ) {
	case C_QR_MSG_NEXT: {
			uchar len = _socket->readChar();
			for( uint i = 0; i < len; i++ ) {
				_msg.append( _socket->readChar() );
			}
		} break;
	case C_QR_MSG_END: {
		//QMessageBox::information( this, "Information", QString( buf+(3*sizeof(char)) ), 0 );
		uchar len = _socket->readChar();
		for( uint i = 0; i < len; i++ ) {
			_msg.append( _socket->readChar() );
		}
		QMessageBox::information( this, "Information", _msg );
		_msg = "";
		} break;
	case C_QR_LEVEL: {
		GainLevel * level = new GainLevel( this );
		level->reinit();
		level->exec();
		_socket->sendAnswer( level->getChoice() );
		delete level;
		} break;
	case C_QR_CHEST: {
		AskChest * chest = new AskChest();
		chest->exec();
		_socket->sendAnswerEnum( chest->getResult() );
		delete chest;
		} break;
	case C_QR_CREATURE_FLEE: {
			AskDialog dialog;
			/// XXX: to improve with name/category of creature
			dialog.setText( "The creatures are fleeing. Do you want to fight them ?" );
			dialog.setYesNo();
			if( dialog.exec() ) {
				_socket->sendAnswerYesNo( false );
			} else {
				_socket->sendAnswerYesNo( true );
			}
		} break;
	case C_QR_CREATURE_MERCENARY: {
			AskDialog dialog;
			/// XXX: to improve with name/category of creature
			dialog.setText( "You can buy these creatures. Do you want to buy them ?" );
			dialog.setYesNo();
			if( dialog.exec() ) {
				_socket->sendAnswerYesNo( true );
			} else {
				_socket->sendAnswerYesNo( false );
			}
		} break;
	case C_QR_CREATURE_JOIN: {
			AskDialog dialog;
			/// XXX: to improve with name/category of creature
			dialog.setText( "The creatures want to join. Do you accept them ?" );
			dialog.setYesNo();
			if( dialog.exec() ) {
				_socket->sendAnswerYesNo( true );
			} else {
				_socket->sendAnswerYesNo( false );
			}
		} break;
	case C_QR_ANSWER:
		logEE( "Should not happen" );
		break;
	}
}
void Game::socketFight()
{
	switch( _socket->getCla2() ) {
	case C_FIGHT_INIT: {
		uchar cla = _socket->readChar();
		uchar lord = _socket->readChar();
		emit sig_fight( getLord( lord ), (CLASS_FIGHTER)cla );
	}
	break;
	case C_FIGHT_LORD:
		logEE( "Should not happen (FIGHT_LORD)" );
		break;
	case C_FIGHT_UNIT:
		logEE( "Should not happen (FIGHT_UNIT)" );
		break;
	case C_FIGHT_END:
		logEE( "Should not happen (FIGHT_END)" );
		break;
	default:
		logEE( "Should not happen (FIGHT)" );
		break;
	}
}

void Game::displayMiniMap( bool state )
{
	if( _miniMap ) {
		if( state ) {
			_miniMap->show();
			_miniMap->redrawMap( _map );
		} else {
			_miniMap->hide();
		}
	}
}

void Game::displayTab( bool state )
{
	if( _tab ) {
		if( state ) {
			_tab->show();
			_tab->setMaximumWidth( _view->width());
		} else {
			_tab->hide();
		}
	}
}

void Game::displayFullScreen( bool state )
{
	if( _tab && _chat && _miniMap) {
		if( state ) {
			_tab->show();
			_chat->show();
			_miniMap->show();
			_tab->setMaximumWidth( _view->width());
		} else {
			_tab->hide();
			_chat->hide();
			_miniMap->hide();
		}
	}
}




//
// ----- GameMessage -----
//

GameMessage::GameMessage( QWidget * parent, const char * name )
	:QDialog( parent, name, true )
{
	_layout = new QVBoxLayout( this );
	_layout->addStretch( 1 );

	_layout->activate();
}

void GameMessage::addText( QString text )
{
	QLabel * label = new QLabel( this );
	label->setText( text );
	FIXEDSIZE( label );
	_layout->addWidget( label );
	_layout->addStretch( 1 );
}

void GameMessage::addPixmap( QPixmap * pixmap )
{
	QLabel * label = new QLabel( this );
	label->setPixmap( * pixmap );
	FIXEDSIZE( label );
	_layout->addWidget( label );
	_layout->addStretch( 1 );
}












