#include "TradeWidget.h"
#include <cassert>
#include "softProj\settings.h"
#include "../../streams/ErrorStream.h"

extern KODIAK_DEBUG_STREAM KODIAK_DEBUG_COUT;

std::string tradingResultToString(ETradingResult tradeResult) 
{
	switch (tradeResult) 
	{
	case TR_DONE:
		return PROTOCOL_TRADE_RESULT_DONE;
	case TR_FIRST_FORTRESS_WEIGHT_LIMIT:
		return PROTOCOL_TRADE_RESULT_FIRST_FORTRESS_WEIGHT_LIMIT;
	case TR_SECOND_FORTRESS_WEIGHT_LIMIT:
		return PROTOCOL_TRADE_RESULT_SECOND_FORTRESS_WEIGHT_LIMIT;
	case TR_FIRST_FORTRESS_CAPACITY_LIMIT:
		return PROTOCOL_TRADE_RESULT_FIRST_FORTRESS_CAPACITY_LIMIT;
	case TR_SECOND_FORTRESS_CAPACITY_LIMIT:
		return PROTOCOL_TRADE_RESULT_SECOND_FORTRESS_CAPACITY_LIMIT;
	case TR_FIRST_FORTRESS_NOT_STORING_ITEMS:
		return PROTOCOL_TRADE_RESULT_FIRST_FORTRESS_NOT_STORING_ITEMS;
	case TR_SECOND_FORTRESS_NOT_STORING_ITEMS:
		return PROTOCOL_TRADE_RESULT_SECOND_FORTRESS_NOT_STORING_ITEMS;
	case TR_FIRST_FORTRESS_MAGNETICAL_GRIDS_LACK:
		return PROTOCOL_TRADE_RESULT_FIRST_FORTRESS_MAGNETICAL_GRIDS_LACK;
	case TR_SECOND_FORTRESS_MAGNETICAL_GRIDS_LACK:
		return PROTOCOL_TRADE_RESULT_SECOND_FORTRESS_MAGNETICAL_GRIDS_LACK;
	case TR_FIRST_FORTRESS_TRANSPORT_CONTAINERS_LACK:
		return PROTOCOL_TRADE_RESULT_FIRST_FORTRESS_TRANSPORT_CONTAINERS_LACK;
	case TR_SECOND_FORTRESS_TRANSPORT_CONTAINERS_LACK:
		return PROTOCOL_TRADE_RESULT_SECOND_FORTRESS_TRANSPORT_CONTAINERS_LACK;
	case TR_FIRST_FORTRESS_ENERGETIC_CELLS_LACK:
		return PROTOCOL_TRADE_RESULT_FIRST_FORTRESS_ENERGETIC_CELLS_LACK;
	case TR_SECOND_FORTRESS_ENERGETIC_CELLS_LACK:
		return PROTOCOL_TRADE_RESULT_SECOND_FORTRESS_ENERGETIC_CELLS_LACK;
	case TR_NOT_IN_RANGE:
		return PROTOCOL_TRADE_RESULT_NOT_IN_RANGE;
	case TR_UNKNOWN_FAIL:
		return PROTOCOL_TRADE_RESULT_UNKNOWN_FAIL;
	}

	return "";
}

TradeWidget::TradeWidget(QWidget *parent) : QWidget(parent), ui_(new Ui::TradeWidget) {
    ui_->setupUi(this);


	createTradeInvitationDialog();
	createMessageDialog();
	createCommitDialog();

	isSynchronizing_ = false;

	tradeRole_ = PROTOCOL_TRADE_ROLE_NONE;
	commitRole_ = TRADE_COMMIT_ROLE_NONE;

	ownedItemsTable_ = new TradeTable(this, TRADE_TABLE_OWNED, false);
	ownedItemsTable_->setTable(ui_->ownedItemsTable);
	ownedItemsTable_->setTitle(ui_->ownedItemsNameButton);
	ownedItemsTable_->setSearchButton(ui_->ownedItemsSearchButton);
	ownedItemsTable_->setShowAllButton(ui_->ownedItemsAllButton);
	ownedItemsTable_->setSearchEdit(ui_->ownedItemsSearchEdit);
    ownedItemsTable_->connectSignals();	

	ownedOfferTable_ = new TradeTable(this, TRADE_TABLE_OWNED_OFFERS, false);
	ownedOfferTable_->setTable(ui_->giveItemsTable);
	ownedOfferTable_->setTitle(ui_->giveItemsNameButton);
	ownedOfferTable_->setSearchButton(ui_->giveItemsSearchButton);
	ownedOfferTable_->setShowAllButton(ui_->giveItemsAllButton);
	ownedOfferTable_->setSearchEdit(ui_->giveItemsSearchEdit);
    ownedOfferTable_->connectSignals();

	enemyOfferTable_ = new TradeTable(this, TRADE_TABLE_ENEMY_OFFERS, true);
	enemyOfferTable_->setTable(ui_->getItemsTable);
	enemyOfferTable_->setTitle(ui_->getItemsNameButton);
	enemyOfferTable_->setSearchButton(ui_->getItemsSearchButton);
    enemyOfferTable_->setShowAllButton(ui_->getItemsAllButton);
	enemyOfferTable_->setSearchEdit(ui_->getItemsSearchEdit);
    enemyOfferTable_->connectSignals();

	enemyItemsTable_ = new TradeTable(this, TRADE_TABLE_ENEMY, true);
	enemyItemsTable_->setTable(ui_->enemyItemsTable);
	enemyItemsTable_->setTitle(ui_->enemyItemsNameButton);
	enemyItemsTable_->setSearchButton(ui_->enemyItemsSearchButton);
    enemyItemsTable_->setShowAllButton(ui_->enemyItemsAllButton);
	enemyItemsTable_->setSearchEdit(ui_->enemyItemsSearchEdit);
    enemyItemsTable_->connectSignals();

	ownedFortressesTable_ = new FortressTable(this, FORTRESS_TABLE_OWNED);
	ownedFortressesTable_->setTable(ui_->ownedFortressesTable);
	ownedFortressesTable_->setTitle(ui_->ownedFortressesNameButton);
	ownedFortressesTable_->setSearchButton(ui_->ownedFortressesSearchButton);
    ownedFortressesTable_->setShowAllButton(ui_->ownedFortressesAllButton);
	ownedFortressesTable_->setSearchEdit(ui_->ownedFortressesSearchEdit);
    ownedFortressesTable_->connectSignals();

	ownedSecondFortressesTable_ = new FortressTable(this, FORTRESS_TABLE_SECOND_OWNED);
	ownedSecondFortressesTable_->setTable(ui_->ownedFortressesOpositeTable);
	ownedSecondFortressesTable_->setTitle(ui_->ownedFortressesOpositeNameButton);
	ownedSecondFortressesTable_->setSearchButton(ui_->ownedFortressesOpositeSearchButton);
    ownedSecondFortressesTable_->setShowAllButton(ui_->ownedFortressesOpositeAllButton);
	ownedSecondFortressesTable_->setSearchEdit(ui_->ownedFortressesOpositeSearchEdit);
    ownedSecondFortressesTable_->connectSignals();

	enemyFortressesTable_ = new FortressTable(this, FORTRESS_TABLE_ENEMY);
	enemyFortressesTable_->setTable(ui_->enemyFortressesTable);
	enemyFortressesTable_->setTitle(ui_->enemyFortressesNameButton);
	enemyFortressesTable_->setSearchButton(ui_->enemyFortressesSearchButton);
    enemyFortressesTable_->setShowAllButton(ui_->enemyFortressesAllButton);
	enemyFortressesTable_->setSearchEdit(ui_->enemyFortressesSearchEdit);
    enemyFortressesTable_->connectSignals();

	stepSelectOwnedFortress_ = QString::fromUtf16(L"Vyber svou pevnost, která se zúčastní obchodu");
	stepSelectSecondOwnedFortress_ = QString::fromUtf16(L"Vyber svou nebo protihráčovu pevnost, která se zůčastní obchodu, nebo vyber možnost vyhazování do vesmíru");
	stepAcceptStartAndWaitForStartAcceptance_ = QString::fromUtf16(L"Nyní můžeš potvrdit zahájení obchodu. Pak ještě musíš počkat na potvrzení protihráče");
	stepAcceptStart_ = QString::fromUtf16(L"Nyní můžeš potvrdit zahájení obchodu");
	stepWaitForStartAcceptance_ = QString::fromUtf16(L"Počkej dokud protihráč nepotvrdí zahájení obchodu");
	stepCommitTrade_ = QString::fromUtf16(L"Nyní můžeš potvrdit vytvořenou nabídku");
	stepInvitationSentWaitingForPartnerDecision_ = QString::fromUtf16(L"Poslal jsi protihráči pozvánku, počkej na potvrzení");

	partnerTradeStep_ = QString::fromUtf16(L"Nyní můžeš nabízet předměty protihráči a sledovat jeho nabídku");
	selfTradeStep_ = QString::fromUtf16(L"Nyní můžeš vytvořit seznamy předmětů pro přesun");

	ui_->selfPartner->setNone();
	ui_->enemyPartner->setNone();

	tradeOfferDialog_ = NULL;
	currentState_ = TRADE_MOVEMENT_STATE_DIRECTION_PARTNER_ITEMS;
	selectedRow_ = 0;

	ui_->ownedItemsTable->horizontalHeader()->setResizeMode(QHeaderView::Fixed);
	ui_->giveItemsTable->horizontalHeader()->setResizeMode(QHeaderView::Fixed);
	ui_->getItemsTable->horizontalHeader()->setResizeMode(QHeaderView::Fixed);
	ui_->enemyItemsTable->horizontalHeader()->setResizeMode(QHeaderView::Fixed);

	bool connected = true;
	connected = connected && connect(ui_->submitButton, SIGNAL(clicked(bool)), this, SLOT(submitButtonClickedSlot()));
	connected = connected && connect(ui_->cancelButton, SIGNAL(clicked(bool)), this, SLOT(cancelButtonClickedSlot()));

	connected = connected && connect(ui_->ownedDeuteriumSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedDeuteriumChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedEnergySlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedEnergyChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedHeavyWaterSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedHeavyWaterChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedIlmeniteSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedIlmeniteChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedPlasmaSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedPlasmaChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedTitanSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedTitanChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedUlreaSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedUlreaChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->ownedCrystalsSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(ownedCrystalsChangedSlot(unsigned long long)));

	connected = connected && connect(ui_->enemyDeuteriumSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyDeuteriumChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyEnergySlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyEnergyChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyHeavyWaterSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyHeavyWaterChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyIlmeniteSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyIlmeniteChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyPlasmaSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyPlasmaChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyTitanSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyTitanChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyUlreaSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyUlreaChangedSlot(unsigned long long)));
	connected = connected && connect(ui_->enemyCrystalsSlider, SIGNAL(valueChangedSignal(unsigned long long)), this, SLOT(enemyCrystalsChangedSlot(unsigned long long)));

	connected = connected && connect(ui_->tradeWithSpaceButton, SIGNAL(clicked(bool)), this, SLOT(tradeWithSpaceButtonClickedSlot()));

	ui_->ownedDeuteriumSlider->setTracking(false);
	ui_->ownedEnergySlider->setTracking(false);
	ui_->ownedHeavyWaterSlider->setTracking(false);
	ui_->ownedIlmeniteSlider->setTracking(false);
	ui_->ownedPlasmaSlider->setTracking(false);
	ui_->ownedTitanSlider->setTracking(false);
	ui_->ownedUlreaSlider->setTracking(false);
	ui_->ownedCrystalsSlider->setTracking(false);

	ui_->enemyDeuteriumSlider->setTracking(false);
	ui_->enemyEnergySlider->setTracking(false);
	ui_->enemyHeavyWaterSlider->setTracking(false);
	ui_->enemyIlmeniteSlider->setTracking(false);
	ui_->enemyPlasmaSlider->setTracking(false);
	ui_->enemyTitanSlider->setTracking(false);
	ui_->enemyUlreaSlider->setTracking(false);
	ui_->enemyCrystalsSlider->setTracking(false);

	QColor fontColor = QColor::fromRgb(40, 40, 40);

	ui_->ownedDeuteriumSlider->setFontColor(fontColor);
	ui_->ownedEnergySlider->setFontColor(fontColor);
	ui_->ownedHeavyWaterSlider->setFontColor(fontColor);
	ui_->ownedIlmeniteSlider->setFontColor(fontColor);
	ui_->ownedPlasmaSlider->setFontColor(fontColor);
	ui_->ownedTitanSlider->setFontColor(fontColor);
	ui_->ownedUlreaSlider->setFontColor(fontColor);
	ui_->ownedCrystalsSlider->setFontColor(fontColor);

	ui_->enemyDeuteriumSlider->setFontColor(fontColor);
	ui_->enemyEnergySlider->setFontColor(fontColor);
	ui_->enemyHeavyWaterSlider->setFontColor(fontColor);
	ui_->enemyIlmeniteSlider->setFontColor(fontColor);
	ui_->enemyPlasmaSlider->setFontColor(fontColor);
	ui_->enemyTitanSlider->setFontColor(fontColor);
	ui_->enemyUlreaSlider->setFontColor(fontColor);
	ui_->enemyCrystalsSlider->setFontColor(fontColor);

	assert(connected && "Signals not connected");

	stepSelectYourFortress(true);
}

void TradeWidget::setOwnedItems(const std::list<warehouse_item_status> & items) {
    clearAllOwnedItems();

    for (std::list<warehouse_item_status>::const_iterator it = items.begin(); it != items.end(); ++it) {
		insertOwnedItem(new TradeItem(*it));
    }
}

void TradeWidget::setEnemyItems(const std::list<warehouse_item_status> & items) {
    clearAllEnemyItems();

    for (std::list<warehouse_item_status>::const_iterator it = items.begin(); it != items.end(); ++it) {
		insertEnemyItem(new TradeItem(*it));
    }
}

void TradeWidget::insertOwnedItem(TradeItem * item) {
    ownedItemsTable_->insertItem(item);
}

void TradeWidget::insertOwnedOffer(TradeItem * item) {
    ownedOfferTable_->insertItem(item);
}

void TradeWidget::insertEnemyOffer(TradeItem * item) {
    enemyOfferTable_->insertItem(item);
}

void TradeWidget::insertEnemyItem(TradeItem * item) {
    enemyItemsTable_->insertItem(item);
}

void TradeWidget::clearAllOwnedItems() {
    ownedItemsTable_->clearAllContent();
}

void TradeWidget::clearAllGiveItems() {
    ownedOfferTable_->clearAllContent();
}

void TradeWidget::clearallGetItems() {
    enemyOfferTable_->clearAllContent();
}

void TradeWidget::clearAllEnemyItems() {
    enemyItemsTable_->clearAllContent();
}

TradeWidget::~TradeWidget()
{
    delete ui_;

    delete ownedItemsTable_;
    delete ownedOfferTable_;
    delete enemyOfferTable_;

	delete ownedFortressesTable_;
	delete ownedSecondFortressesTable_;
	delete enemyFortressesTable_;

	if (tradeOfferDialog_ != NULL) {
		delete tradeOfferDialog_;
	}

	if (tradeInvitationDialog_ != NULL) {
		delete tradeInvitationDialog_;
	}

	if (commitDialog_ != NULL) {
		delete commitDialog_;
	}
}

void TradeWidget::showOfferDialog(TradeItem * item) {
	if (tradeOfferDialog_ == NULL) {
		tradeOfferDialog_ = new TradeOfferDialog(this);
																						   
		bool connected = connect(tradeOfferDialog_, SIGNAL(submitSignal()), this, SLOT(submitTradeOfferSlot()));
		connected = connected && connect(tradeOfferDialog_, SIGNAL(cancelSignal()), this, SLOT(cancelTradeOfferSlot()));
		connected = connected && connect(tradeOfferDialog_, SIGNAL(rejected()), this, SLOT(rejectDialogSlot()));
		assert(connected && "Signals not connected");
	}

	emit showDialogSignal();
	tradeOfferDialog_->setItem(item);
	tradeOfferDialog_->setWindowFlags(Qt::SplashScreen);

	tradeOfferDialog_->show();
	tradeOfferDialog_->raise();
	tradeOfferDialog_->activateWindow();
}

void TradeWidget::ownedFortressClicked(FortressItemRow * item, int row) {
	selectedRow_ = row;
	setSelfPartner(item);	

	ui_->currentDescriptionLabel->setText(stepSelectSecondOwnedFortress_);
	setActiveStep(ui_->step2Label);	

	ui_->submitButton->setEnabled(false);
	ui_->cancelButton->setEnabled(false);
	
	ui_->tradeWithSpaceButton->setEnabled(true);

	ownedFortressesTable_->setRowAsClicked(row);
	ownedSecondFortressesTable_->setNoRowAsClicked();
	enemyFortressesTable_->setNoRowAsClicked();

	changeStep(TRADE_STEP_BEFORE_SELECT_PARTNER_FORTRESS);
}

void TradeWidget::ownedSecondFortressClicked(FortressItemRow * item, int row) {
	selectedRow_ = row;
	setEnemyPartner(item);

	ui_->currentDescriptionLabel->setText(stepAcceptStart_);
	setActiveStep(ui_->step3Label);	

	ui_->submitButton->setEnabled(true);
	ui_->cancelButton->setEnabled(false);

	ui_->submitButton->setText(QString::fromUtf16(L"Zahájit obchod"));

	ownedSecondFortressesTable_->setRowAsClicked(row);
	enemyFortressesTable_->setNoRowAsClicked();

	changeStep(TRADE_STEP_BEFORE_SEND_INVITATION);
}

void TradeWidget::enemyFortressClicked(FortressItemRow * item, int row) {
	selectedRow_ = row;
	setEnemyPartner(item);	

	ui_->currentDescriptionLabel->setText(stepAcceptStartAndWaitForStartAcceptance_);
	setActiveStep(ui_->step3Label);	

	ui_->submitButton->setText(QString::fromUtf16(L"Poslat protihráči žádost o obchod"));

	ui_->submitButton->setEnabled(true);
	ui_->cancelButton->setEnabled(false);

	enemyFortressesTable_->setRowAsClicked(row);
	ownedSecondFortressesTable_->setNoRowAsClicked();

	changeStep(TRADE_STEP_BEFORE_SEND_INVITATION);
}

void TradeWidget::changeState(EMovementStateDirection state) {
	currentState_ = state;
}

bool TradeWidget::isInState(EMovementStateDirection state) {
	return currentState_ = state;
}

void TradeWidget::signalMoveTradeItem(TradeItem * item, const std::string & tradeDirection, unsigned long long working, unsigned long long damaged) {	
	if (working == 0 && damaged == 0) {
		return;
	}

	trade_client_movement_data tradeData;

	tradeData.itemId = item->getWarehouseItem().id;

	tradeData.selfFortressId = ui_->selfPartner->getFortressId();
	tradeData.partnerFortressId = ui_->enemyPartner->getFortressId();

	tradeData.working = working;
	tradeData.damaged = damaged;
	tradeData.tradeDirection = tradeDirection;
	tradeData.patternName = item->getWarehouseItem().patternName;

	emit moveTradeItemSignal(tradeData);
}

void TradeWidget::ownedItemClicked(TradeItem * item) {
	if (item->getCount() == 1) {
		signalMoveTradeItem(item, TRADE_DIRECTION_OWNED_OFFER, 1, 0);
	}
	else {
		changeState(TRADE_MOVEMENT_STATE_DIRECTION_OWNED_OFFER);
		showOfferDialog(item);
	}
}

void TradeWidget::ownedOfferClicked(TradeItem * item) {
	if (item->getCount() == 1) {
		signalMoveTradeItem(item, TRADE_DIRECTION_OWNED_ITEMS, 1, 0);
	}
	else {
		changeState(TRADE_MOVEMENT_STATE_DIRECTION_OWNED_ITEMS);
		showOfferDialog(item);
	}
}

void TradeWidget::enemyItemClicked(TradeItem * item) {
	if (item->getCount() == 1) {
		signalMoveTradeItem(item, TRADE_DIRECTION_PARTNER_OFFER, 1, 0);
	}
	else {
		changeState(TRADE_MOVEMENT_STATE_DIRECTION_PARTNER_OFFER);
		showOfferDialog(item);
	}
}

void TradeWidget::enemyOfferClicked(TradeItem * item) {
	if (item->getCount() == 1) {
		signalMoveTradeItem(item, TRADE_DIRECTION_PARTNER_ITEMS, 1, 0);
	}
	else {
		changeState(TRADE_MOVEMENT_STATE_DIRECTION_PARTNER_ITEMS);
		showOfferDialog(item);
	}
}

bool TradeWidget::moveItemFromTableToTable(id_t itemId, TradeTable * sourceTable, TradeTable * targetTable, unsigned long long working, unsigned long long damaged) {

	TradeItem * item = sourceTable->findItemById(itemId);

	if (item == NULL) {
		KODIAK_DEBUG_COUT << "Server sent item movement, but item not in a table";		
		return false;
	}

	int row = sourceTable->findRowOfItem(itemId);

	if (row == -1) {
		KODIAK_DEBUG_COUT << "Server sent item movement, but item not in a table";		
		return false;
	}

	switch (item->type) {
	case BASIC_TRADE_ITEM:
		sourceTable->removeRowAndItem(item, row);
		targetTable->insertItem(item);
		break;
	case STACKABLE_TRADE_ITEM:
		if (item->getCount() == 1) {
			TradeItem * changedItem = moveItemFrom(sourceTable, item, row, 1, 0);
			moveItemTo(targetTable, changedItem);
		}
		else {
			TradeItem * changedItem = moveItemFrom(sourceTable, item, row, working, damaged);
			moveItemTo(targetTable, changedItem);
		}
		break;
	}

	return true;
}

bool TradeWidget::moveItemFromTableAndDeleteSplit(const trade_movement_data & tradeData, TradeTable * sourceTable) {

	TradeItem * item = sourceTable->findItemById(tradeData.item.id);

	if (item == NULL) {
		KODIAK_DEBUG_COUT << "Server sent item movement, but item not in a table";		
		return false;
	}

	int row = sourceTable->findRowOfItem(tradeData.item.id);

	if (row == -1) {
		KODIAK_DEBUG_COUT << "Server sent item movement, but item not in a table";		
		return false;
	}

	TradeItem * itemSplit = moveItemFrom(sourceTable, item, row, tradeData.item.working, tradeData.item.damaged);
	delete itemSplit;

	return true;
}

void TradeWidget::submitTradeOfferSlot() {
	
	unsigned long offerWorking = tradeOfferDialog_->getWorking();
	unsigned long offerDamaged = tradeOfferDialog_->getDamaged();

	TradeItem * item = tradeOfferDialog_->getItem();

	emit hideDialogSignal();
	tradeOfferDialog_->accept();

	switch (currentState_) {
		case TRADE_MOVEMENT_STATE_DIRECTION_OWNED_OFFER:
		{
			signalMoveTradeItem(item, TRADE_DIRECTION_OWNED_OFFER, offerWorking, offerDamaged);
			break;
		}
		case TRADE_MOVEMENT_STATE_DIRECTION_OWNED_ITEMS:
		{
			signalMoveTradeItem(item, TRADE_DIRECTION_OWNED_ITEMS, offerWorking, offerDamaged);
			break;
		}
		case TRADE_MOVEMENT_STATE_DIRECTION_PARTNER_OFFER:
		{
			signalMoveTradeItem(item, TRADE_DIRECTION_PARTNER_OFFER, offerWorking, offerDamaged);
			break;
		}
		case TRADE_MOVEMENT_STATE_DIRECTION_PARTNER_ITEMS:
		{
			signalMoveTradeItem(item, TRADE_DIRECTION_PARTNER_ITEMS, offerWorking, offerDamaged);
			break;
		}
	}
}

TradeItem * TradeWidget::moveItemFrom(TradeTable * sourceTable, TradeItem * item, int row, unsigned long offerWorking, unsigned long offerDamaged) {
	unsigned long offerTotal = offerWorking + offerDamaged;

	if (item->getCount() == offerTotal) {
		// If item now has zero count, we can remove it from first table
		sourceTable->removeRowAndItem(item, row);

		// And we can put this item to second table, so just return this one
		return item;
	}
	else {
		// Remove moved count from item
		item->getWarehouseItem().working -= offerWorking;
		item->getWarehouseItem().damaged -= offerDamaged;

		// If item still has positive count, we just decrease count in first table
		sourceTable->removeCount(row, offerWorking, offerDamaged);

		// Create new item for second table, becasuse the old one still stays in first table
		TradeItem * itemSplit = new TradeItem(*item);
		itemSplit->getWarehouseItem().working = offerWorking;
		itemSplit->getWarehouseItem().damaged = offerDamaged;
		return itemSplit;
	}
}

void TradeWidget::moveItemTo(TradeTable * targetTable, TradeItem * item) {
	TradeItem * oldItem = targetTable->findItemById(item->getWarehouseItem().id);	

	if (oldItem != NULL) {
		// Item with this id is already in second table, but it can be invisible, because it 
		// does not have to fit to the current filter

		// Add moved count to item
		oldItem->getWarehouseItem().working += item->getWarehouseItem().working;
		oldItem->getWarehouseItem().damaged += item->getWarehouseItem().damaged;

		// Find if item is visible
		int row = targetTable->findRowOfItem(item->getWarehouseItem().id);

		if (row > - 1) {
			// Item is visible, so just increase items count in table
			targetTable->addCount(row, item->getWarehouseItem().working, item->getWarehouseItem().damaged);			
		}
		else {
			// Item is invisible, so do not increase count in table
		}

		delete item;
	}
	else {
		// Insert item into second table, it was not there yet
		targetTable->insertItem(item);
	}	
}

void TradeWidget::cancelTradeOfferSlot() {
	emit hideDialogSignal();
	tradeOfferDialog_->reject();
}

void TradeWidget::stepPartnerTrade() {
	tradeType_ = TRADE_TRADE_WITH_ENEMY;
	ui_->cantSeeEnemyItemsLabel->setVisible(true);
}

void TradeWidget::stepSelfTrade() {
	tradeType_ = TRADE_TRADE_WITH_SELF;
	ui_->cantSeeEnemyItemsLabel->setVisible(false);
}

void TradeWidget::setOwnedFortresses(const std::vector<SimpleItem> & fortresses) {
    clearAllOwnedFortresses();

    for (std::vector<SimpleItem>::const_iterator it = fortresses.begin(); it != fortresses.end(); ++it) {
		FightWidgetRowWidget * itemWidget = insertOwnedFortress(new FortressItemRow(*it, it->fortressType, true));
		itemWidget->setAsBuildShell(false);
    }
}

void TradeWidget::setSecondOwnedFortresses(const std::vector<SimpleItem> & fortresses) {
    clearAllOwnedOppositeFortresses();

    for (std::vector<SimpleItem>::const_iterator it = fortresses.begin(); it != fortresses.end(); ++it) {
		FightWidgetRowWidget * itemWidget = insertSecondOwnedFortress(new FortressItemRow(*it, it->fortressType, true));
		itemWidget->setAsBuildShell(it->isShell);
    }
}

void TradeWidget::setEnemyFortresses(const std::vector<SimpleItem> & fortresses) {
    clearAllEnemyFortresses();

    for (std::vector<SimpleItem>::const_iterator it = fortresses.begin(); it != fortresses.end(); ++it) {
		FightWidgetRowWidget * itemWidget = insertEnemyFortress(new FortressItemRow(*it, it->fortressType, false));
		itemWidget->setAsBuildShell(it->isShell);
    }
}

void TradeWidget::clearAllOwnedFortresses() {
    ownedFortressesTable_->clearAllContent();
}

void TradeWidget::clearAllOwnedOppositeFortresses() {
	ownedSecondFortressesTable_->clearAllContent();
}
void TradeWidget::clearAllEnemyFortresses() {
	enemyFortressesTable_->clearAllContent();
}

FightWidgetRowWidget * TradeWidget::insertOwnedFortress(FortressItemRow * item) {
	return ownedFortressesTable_->insertItem(item);
}

FightWidgetRowWidget * TradeWidget::insertSecondOwnedFortress(FortressItemRow * item) {
	return ownedSecondFortressesTable_->insertItem(item);
}

FightWidgetRowWidget * TradeWidget::insertEnemyFortress(FortressItemRow * item) {
	return enemyFortressesTable_->insertItem(item);
}

void TradeWidget::setSelfPartner(FortressItemRow * item) {
	ui_->selfPartner->setPartner(item->getId(), item->getName(), item->getRealmName(), item->isOwned(), item->isShip());
	emit tradePartnerFortressesSignal(item->getId());
}

void TradeWidget::setEnemyPartner(FortressItemRow * item) {
	ui_->enemyPartner->setPartner(item->getId(), item->getName(), item->getRealmName(), item->isOwned(), item->isShip());
}

void TradeWidget::setActiveStep(QLabel * stepLabel) {
	ui_->step1Label->setProperty("active", false);
	ui_->step1Label->setStyleSheet(ui_->step1Label->styleSheet());

	ui_->step2Label->setProperty("active", false);
	ui_->step2Label->setStyleSheet(ui_->step2Label->styleSheet());

	ui_->step3Label->setProperty("active", false);
	ui_->step3Label->setStyleSheet(ui_->step3Label->styleSheet());

	ui_->step4Label->setProperty("active", false);
	ui_->step4Label->setStyleSheet(ui_->step4Label->styleSheet());

	ui_->step5Label->setProperty("active", false);
	ui_->step5Label->setStyleSheet(ui_->step5Label->styleSheet());

	stepLabel->setProperty("active", true);
	stepLabel->setStyleSheet(stepLabel->styleSheet());
}

void TradeWidget::changeStep(ETradeStep step) {
	this->currentStep_ = step;
}

void TradeWidget::tradeWithSpaceButtonClickedSlot() {
	ui_->enemyPartner->setSpace();
	changeStep(TRADE_STEP_BEFORE_SEND_INVITATION);
	sendTradeInvitation();
}

void TradeWidget::submitButtonClickedSlot() {
	switch (currentStep_) {
	case TRADE_STEP_BEFORE_SEND_INVITATION:
		if (!ui_->enemyPartner->isOwned()) {
			trade_invitation_data invitation;

			invitation.hostFortressId = ui_->selfPartner->getFortressId();
			invitation.hostFortressName = ui_->selfPartner->getFortressName();
			invitation.hostName = ui_->selfPartner->getRealmName();
			invitation.hostIsShip = ui_->selfPartner->isShip();

			invitation.invitedFortressId = ui_->enemyPartner->getFortressId();
			invitation.invitedFortressName = ui_->enemyPartner->getFortressName();
			invitation.invitedName = ui_->enemyPartner->getRealmName();
			invitation.hostIsShip = ui_->enemyPartner->isShip();
			
			invitation.invitedIsShip = true;

			tradeInvitationDialog_->setDialog(invitation, false);
		}

		sendTradeInvitation();

		break;
	case TRADE_STEP_OFFER_ITEMS:
		emit showDialogSignal();
		commitDialog_->setAsWaitForPartnerDecision();
		signalCommitTrade();		
		break;
	default:
		emit cancelTradeSignal();
	}	
}

void TradeWidget::cancelButtonClickedSlot() {	
	emit cancelTradeSignal();
	stepSelectYourFortress(true);
}

void TradeWidget::startTradeCommon(const trade_invitation_data & invitation) {
	if (!isVisible()) {
		// If widget is not visible, emit signal so that MainWindow can show it
		emit startTradeSignal();
	}

	setActiveStep(ui_->step4Label);

	ui_->stackedWidget->setCurrentWidget(ui_->itemTablesPage);	
	ui_->currentDescriptionLabel->setText(selfTradeStep_);
	ui_->submitButton->setText(QString::fromUtf16(L"Potvrdit nabídku a přesunout předměty"));
	ui_->submitButton->setEnabled(true);
	ui_->cancelButton->setEnabled(true);

	changeStep(TRADE_STEP_OFFER_ITEMS);

	partnerResources_.deuterium = 0;
	partnerResources_.energy = 0;
	partnerResources_.heavyWater = 0;
	partnerResources_.ilmenite = 0;
	partnerResources_.quarkGluonPlasma = 0;
	partnerResources_.titanium = 0;
	partnerResources_.ulrea = 0;	
	partnerResources_.zirconiumCrystal = 0;
}

void TradeWidget::startSelfTrade(const trade_invitation_data & invitation, const trade_data & selfTradeData, const trade_data & partnerTradeData) {
	isSynchronizing_ = true;

	startTradeCommon(invitation);

	ui_->selfPartner->setPartner(invitation.hostFortressId, invitation.hostFortressName,
		invitation.hostName, true, invitation.hostIsShip);

	ui_->enemyPartner->setPartner(invitation.invitedFortressId, invitation.invitedFortressName,
		invitation.invitedName, true, invitation.invitedIsShip);

	ownedOfferTable_->clearAllContent();
	enemyOfferTable_->clearAllContent();
 	setOwnedItems(selfTradeData.tradeItems);
	setEnemyItems(partnerTradeData.tradeItems);

	ui_->ownedCrystalsSlider->setMaximum(selfTradeData.zirconiumCrystal);
	ui_->ownedCrystalsSlider->setMinimum(0);
	ui_->ownedCrystalsSlider->setValue(0);

	ui_->ownedDeuteriumSlider->setMaximum(selfTradeData.deuterium);
	ui_->ownedDeuteriumSlider->setMinimum(0);
	ui_->ownedDeuteriumSlider->setValue(0);

	ui_->ownedHeavyWaterSlider->setMaximum(selfTradeData.heavyWater);
	ui_->ownedHeavyWaterSlider->setMinimum(0);
	ui_->ownedHeavyWaterSlider->setValue(0);

	ui_->ownedIlmeniteSlider->setMaximum(selfTradeData.ilmenite);
	ui_->ownedIlmeniteSlider->setMinimum(0);
	ui_->ownedIlmeniteSlider->setValue(0);

	ui_->ownedPlasmaSlider->setMaximum(selfTradeData.quarkGluonPlasma);
	ui_->ownedPlasmaSlider->setMinimum(0);
	ui_->ownedPlasmaSlider->setValue(0);

	ui_->ownedTitanSlider->setMaximum(selfTradeData.titanium);
	ui_->ownedTitanSlider->setMinimum(0);
	ui_->ownedTitanSlider->setValue(0);

	ui_->ownedUlreaSlider->setMaximum(selfTradeData.ulrea);
	ui_->ownedUlreaSlider->setMinimum(0);
	ui_->ownedUlreaSlider->setValue(0);

	ui_->ownedEnergySlider->setMaximum(selfTradeData.energy);
	ui_->ownedEnergySlider->setMinimum(0);
	ui_->ownedEnergySlider->setValue(0);

	ui_->enemyCrystalsSlider->setVisible(true);
	ui_->enemyCrystalsValue->setVisible(false);
	ui_->enemyCrystalsSlider->setMaximum(partnerTradeData.zirconiumCrystal);
	ui_->enemyCrystalsSlider->setMinimum(0);
	ui_->enemyCrystalsSlider->setValue(0);
	
	ui_->enemyDeuteriumSlider->setVisible(true);
	ui_->enemyDeuteriumValue->setVisible(false);
	ui_->enemyDeuteriumSlider->setMaximum(partnerTradeData.deuterium);
	ui_->enemyDeuteriumSlider->setMinimum(0);
	ui_->enemyDeuteriumSlider->setValue(0);
	
	ui_->enemyHeavyWaterSlider->setVisible(true);
	ui_->enemyHeavyWaterValue->setVisible(false);
	ui_->enemyHeavyWaterSlider->setMaximum(partnerTradeData.heavyWater);
	ui_->enemyHeavyWaterSlider->setMinimum(0);
	ui_->enemyHeavyWaterSlider->setValue(0);
		
	ui_->enemyIlmeniteSlider->setVisible(true);
	ui_->enemyIlmeniteValue->setVisible(false);
	ui_->enemyIlmeniteSlider->setMaximum(partnerTradeData.ilmenite);
	ui_->enemyIlmeniteSlider->setMinimum(0);
	ui_->enemyIlmeniteSlider->setValue(0);
	
	ui_->enemyPlasmaSlider->setVisible(true);
	ui_->enemyPlasmaValue->setVisible(false);
	ui_->enemyPlasmaSlider->setMaximum(partnerTradeData.quarkGluonPlasma);
	ui_->enemyPlasmaSlider->setMinimum(0);
	ui_->enemyPlasmaSlider->setValue(0);
		
	ui_->enemyTitanSlider->setVisible(true);
	ui_->enemyTitanValue->setVisible(false);
	ui_->enemyTitanSlider->setMaximum(partnerTradeData.titanium);
	ui_->enemyTitanSlider->setMinimum(0);
	ui_->enemyTitanSlider->setValue(0);
		
	ui_->enemyUlreaSlider->setVisible(true);
	ui_->enemyUlreaValue->setVisible(false);
	ui_->enemyUlreaSlider->setMaximum(partnerTradeData.ulrea);
	ui_->enemyUlreaSlider->setMinimum(0);
	ui_->enemyUlreaSlider->setValue(0);

	ui_->enemyEnergySlider->setVisible(true);
	ui_->enemyEnergyValue->setVisible(false);
	ui_->enemyEnergySlider->setMaximum(partnerTradeData.energy);
	ui_->enemyEnergySlider->setMinimum(0);
	ui_->enemyEnergySlider->setValue(0);

	ui_->cantSeeEnemyOfferLabel->setVisible(false);
	ui_->cantSeeEnemyItemsLabel->setVisible(false);

	this->tradeRole_ = PROTOCOL_TRADE_ROLE_SELF_TRADER;

	isSynchronizing_ = false;
}

void TradeWidget::startSpaceTrade(const trade_invitation_data & invitation, const trade_data & selfTradeData) {
	isSynchronizing_ = true;

	startTradeCommon(invitation);

	ui_->selfPartner->setPartner(invitation.hostFortressId, invitation.hostFortressName,
		invitation.hostName, true, invitation.hostIsShip);

	ui_->enemyPartner->setSpace();

	ownedOfferTable_->clearAllContent();
	enemyOfferTable_->clearAllContent();
	enemyItemsTable_->clearAllContent();
 	setOwnedItems(selfTradeData.tradeItems);

	ui_->ownedCrystalsSlider->setMaximum(selfTradeData.zirconiumCrystal);
	ui_->ownedCrystalsSlider->setMinimum(0);
	ui_->ownedCrystalsSlider->setValue(0);

	ui_->ownedDeuteriumSlider->setMaximum(selfTradeData.deuterium);
	ui_->ownedDeuteriumSlider->setMinimum(0);
	ui_->ownedDeuteriumSlider->setValue(0);

	ui_->ownedHeavyWaterSlider->setMaximum(selfTradeData.heavyWater);
	ui_->ownedHeavyWaterSlider->setMinimum(0);
	ui_->ownedHeavyWaterSlider->setValue(0);

	ui_->ownedIlmeniteSlider->setMaximum(selfTradeData.ilmenite);
	ui_->ownedIlmeniteSlider->setMinimum(0);
	ui_->ownedIlmeniteSlider->setValue(0);

	ui_->ownedPlasmaSlider->setMaximum(selfTradeData.quarkGluonPlasma);
	ui_->ownedPlasmaSlider->setMinimum(0);
	ui_->ownedPlasmaSlider->setValue(0);

	ui_->ownedTitanSlider->setMaximum(selfTradeData.titanium);
	ui_->ownedTitanSlider->setMinimum(0);
	ui_->ownedTitanSlider->setValue(0);

	ui_->ownedUlreaSlider->setMaximum(selfTradeData.ulrea);
	ui_->ownedUlreaSlider->setMinimum(0);
	ui_->ownedUlreaSlider->setValue(0);

	ui_->ownedEnergySlider->setMaximum(selfTradeData.energy);
	ui_->ownedEnergySlider->setMinimum(0);
	ui_->ownedEnergySlider->setValue(0);

	ui_->enemyCrystalsSlider->setVisible(false);
	ui_->enemyCrystalsValue->setVisible(true);
	ui_->enemyCrystalsValue->setText(QString::number(0));

	ui_->enemyDeuteriumSlider->setVisible(false);
	ui_->enemyDeuteriumValue->setVisible(true);
	ui_->enemyDeuteriumValue->setText(QString::number(0));

	ui_->enemyHeavyWaterSlider->setVisible(false);
	ui_->enemyHeavyWaterValue->setVisible(true);
	ui_->enemyHeavyWaterValue->setText(QString::number(0));

	ui_->enemyIlmeniteSlider->setVisible(false);
	ui_->enemyIlmeniteValue->setVisible(true);
	ui_->enemyIlmeniteValue->setText(QString::number(0));

	ui_->enemyPlasmaSlider->setVisible(false);
	ui_->enemyPlasmaValue->setVisible(true);
	ui_->enemyPlasmaValue->setText(QString::number(0));

	ui_->enemyTitanSlider->setVisible(false);
	ui_->enemyTitanValue->setVisible(true);
	ui_->enemyTitanValue->setText(QString::number(0));

	ui_->enemyUlreaSlider->setVisible(false);
	ui_->enemyUlreaValue->setVisible(true);
	ui_->enemyUlreaValue->setText(QString::number(0));

	ui_->enemyEnergySlider->setVisible(false);
	ui_->enemyEnergyValue->setVisible(true);
	ui_->enemyEnergyValue->setText(QString::number(0));

	ui_->enemyEnergySlider->setVisible(false);
	ui_->enemyEnergyValue->setVisible(true);
	ui_->enemyEnergyValue->setText(QString::number(0));

	ui_->cantSeeEnemyOfferLabel->setVisible(true);
	ui_->cantSeeEnemyOfferLabel->setText(QString::fromUtf16(L"Jsi v režimu vyhazování do vesmíru, vesmír žádné předměty nemá ani nenabízí"));
	ui_->cantSeeEnemyItemsLabel->setVisible(true);
	ui_->cantSeeEnemyItemsLabel->setText(QString::fromUtf16(L"Jsi v režimu vyhazování do vesmíru, vesmír žádné předměty nemá ani nenabízí"));

	this->tradeRole_ = PROTOCOL_TRADE_ROLE_SELF_TRADER;

	isSynchronizing_ = false;
}

void TradeWidget::startPartnerTrade(const trade_invitation_data & invitation, const trade_data & data, bool isHostThisUser) {
	isSynchronizing_ = true;

	startTradeCommon(invitation);

	if (isHostThisUser) {
		ui_->selfPartner->setPartner(invitation.hostFortressId, invitation.hostFortressName,
			invitation.hostName, true, invitation.hostIsShip);

		ui_->enemyPartner->setPartner(invitation.invitedFortressId, invitation.invitedFortressName,
			invitation.invitedName, invitation.hostId == invitation.invitedId, invitation.invitedIsShip);
	}
	else {
		ui_->selfPartner->setPartner(invitation.invitedFortressId, invitation.invitedFortressName,
			invitation.invitedName, true, invitation.invitedIsShip);

		ui_->enemyPartner->setPartner(invitation.hostFortressId, invitation.hostFortressName,
			invitation.hostName, invitation.hostId == invitation.invitedId, invitation.hostIsShip);
	}

	ownedOfferTable_->clearAllContent();
	enemyOfferTable_->clearAllContent();
	enemyItemsTable_->clearAllContent();
 	setOwnedItems(data.tradeItems);

	ui_->ownedCrystalsSlider->setMaximum(data.zirconiumCrystal);
	ui_->ownedCrystalsSlider->setMinimum(0);
	ui_->ownedCrystalsSlider->setValue(0);

	ui_->ownedDeuteriumSlider->setMaximum(data.deuterium);
	ui_->ownedDeuteriumSlider->setMinimum(0);
	ui_->ownedDeuteriumSlider->setValue(0);

	ui_->ownedHeavyWaterSlider->setMaximum(data.heavyWater);
	ui_->ownedHeavyWaterSlider->setMinimum(0);
	ui_->ownedHeavyWaterSlider->setValue(0);

	ui_->ownedIlmeniteSlider->setMaximum(data.ilmenite);
	ui_->ownedIlmeniteSlider->setMinimum(0);
	ui_->ownedIlmeniteSlider->setValue(0);

	ui_->ownedPlasmaSlider->setMaximum(data.quarkGluonPlasma);
	ui_->ownedPlasmaSlider->setMinimum(0);
	ui_->ownedPlasmaSlider->setValue(0);

	ui_->ownedTitanSlider->setMaximum(data.titanium);
	ui_->ownedTitanSlider->setMinimum(0);
	ui_->ownedTitanSlider->setValue(0);

	ui_->ownedUlreaSlider->setMaximum(data.ulrea);
	ui_->ownedUlreaSlider->setMinimum(0);
	ui_->ownedUlreaSlider->setValue(0);

	ui_->ownedEnergySlider->setMaximum(data.energy);
	ui_->ownedEnergySlider->setMinimum(0);
	ui_->ownedEnergySlider->setValue(0);

	ui_->enemyCrystalsSlider->setVisible(false);
	ui_->enemyCrystalsValue->setVisible(true);
	ui_->enemyCrystalsValue->setText(QString::number(0));

	ui_->enemyDeuteriumSlider->setVisible(false);
	ui_->enemyDeuteriumValue->setVisible(true);
	ui_->enemyDeuteriumValue->setText(QString::number(0));

	ui_->enemyHeavyWaterSlider->setVisible(false);
	ui_->enemyHeavyWaterValue->setVisible(true);
	ui_->enemyHeavyWaterValue->setText(QString::number(0));

	ui_->enemyIlmeniteSlider->setVisible(false);
	ui_->enemyIlmeniteValue->setVisible(true);
	ui_->enemyIlmeniteValue->setText(QString::number(0));

	ui_->enemyPlasmaSlider->setVisible(false);
	ui_->enemyPlasmaValue->setVisible(true);
	ui_->enemyPlasmaValue->setText(QString::number(0));

	ui_->enemyTitanSlider->setVisible(false);
	ui_->enemyTitanValue->setVisible(true);
	ui_->enemyTitanValue->setText(QString::number(0));

	ui_->enemyUlreaSlider->setVisible(false);
	ui_->enemyUlreaValue->setVisible(true);
	ui_->enemyUlreaValue->setText(QString::number(0));

	ui_->enemyEnergySlider->setVisible(false);
	ui_->enemyEnergyValue->setVisible(true);
	ui_->enemyEnergyValue->setText(QString::number(0));

	ui_->enemyEnergySlider->setVisible(false);
	ui_->enemyEnergyValue->setVisible(true);
	ui_->enemyEnergyValue->setText(QString::number(0));

	ui_->cantSeeEnemyOfferLabel->setVisible(false);
	ui_->cantSeeEnemyItemsLabel->setVisible(true);
	ui_->cantSeeEnemyItemsLabel->setText(QString::fromUtf16(L"Jsi v režimu obchodování s protihráčem. Při obchodování s protihráčem nemůžeš vidět jeho předměty"));

	this->tradeRole_ = PROTOCOL_TRADE_ROLE_PARTNER_TRADER;

	isSynchronizing_ = false;
}

void TradeWidget::sendTradeInvitation() {
	changeStep(TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION);
	setActiveStep(ui_->step4Label);
	ui_->currentDescriptionLabel->setText(stepInvitationSentWaitingForPartnerDecision_);
	emit inviteTradePartnerSignal(ui_->selfPartner->getFortressId(), ui_->enemyPartner->getFortressId());		
}

void TradeWidget::answerSendTradeInvitation(const trade_invitation_data & invitation, const trade_data & selfTradeData, const std::string & reason, const std::string & tradeRole) {
	if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {
		if (tradeRole == PROTOCOL_TRADE_ROLE_SPACE_TRADER) {
			startSpaceTrade(invitation, selfTradeData);
			emit hideDialogSignal();
			tradeInvitationDialog_->close();
		}

		this->tradeRole_ = tradeRole;
	}
	else {
		// Client received acknowledgement from server that he received his invitation, but he did not send any, just ignore it
		KODIAK_DEBUG_COUT << "TRADE WARNING: Client received trade invitation acknowledgement, but did not send any invitation";
	}
}

void TradeWidget::answerSendTradeInvitationFromBuild(const trade_invitation_data & invitation, const trade_data & selfTradeData, const trade_data & partnerTradeData, const std::string & reason, const std::string & tradeRole) {
	if (tradeRole == PROTOCOL_TRADE_ROLE_SELF_TRADER || tradeRole == PROTOCOL_TRADE_ROLE_LOOT_TRADER) {
		startSelfTrade(invitation, selfTradeData, partnerTradeData);
	}
}

void TradeWidget::answerSendTradeInvitation(const trade_invitation_data & invitation, const trade_data & selfTradeData, const trade_data & partnerTradeData, const std::string & reason, const std::string & tradeRole) {
	if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {
		if (tradeRole == PROTOCOL_TRADE_ROLE_SELF_TRADER || tradeRole == PROTOCOL_TRADE_ROLE_LOOT_TRADER) {
			startSelfTrade(invitation, selfTradeData, partnerTradeData);
		}

		this->tradeRole_ = tradeRole;
	}
	else {
		// Client received acknowledgement from server that he received his invitation, but he did not send any, just ignore it
		KODIAK_DEBUG_COUT << "TRADE WARNING: Client received trade invitation acknowledgement, but did not send any invitation";
	}
}

void TradeWidget::answerSendTradeInvitation(const trade_invitation_data & invitation, const std::string & reason, const std::string & tradeRole) {
	if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {
		if (tradeRole == PROTOCOL_TRADE_ROLE_HOST) {
			tradeInvitationDialog_->setAsWaitForPartnerDecisionServerReceived();	
		}

		this->tradeRole_ = tradeRole;
	}
	else {
		// Client received acknowledgement from server that he received his invitation, but he did not send any, just ignore it
		KODIAK_DEBUG_COUT << "TRADE WARNING: Client received trade invitation acknowledgement, but did not send any invitation";
	}
}

void TradeWidget::receiveTradeInvitationDecision(const trade_invitation_data & invitation) {
	if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {
		tradeInvitationDialog_->setAsPartnerRejected();
		changeStep(TRADE_STEP_BEFORE_SEND_INVITATION);
	}
	else {
		// Client received invitation that he was not waiting for, so just ignore it
		KODIAK_DEBUG_COUT << "TRADE WARNING: Client received trade invitation decision, but was not waiting for it";
	}
}

void TradeWidget::receiveTradeInvitationDecision(const trade_invitation_data & invitation, const trade_data & tradeData) {
	if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {
		emit hideDialogSignal();
		tradeInvitationDialog_->close();
		startPartnerTrade(invitation, tradeData, true);
	}
	else {
		// Client received invitation that he was not waiting for, so just ignore it
		KODIAK_DEBUG_COUT << "TRADE WARNING: Client received trade invitation decision, but was not waiting for it";
	}
}

void TradeWidget::answerDecideTradeInvitation(const trade_invitation_data & invitation) {
	if (currentStep_ == TRADE_STEP_INVITATION_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE) {	
		// Nothing to do, because client does not need to wait for acknowledgement to cancel trade
	}
}

void TradeWidget::answerDecideTradeInvitation(const trade_invitation_data & invitation, const trade_data & tradeData) {
	if (currentStep_ == TRADE_STEP_INVITATION_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE) {
		startPartnerTrade(invitation, tradeData, false);
	}
	else {
		// Client received acknowledgement that server received his invitation decision, but it did not send any, so just ignore it
		KODIAK_DEBUG_COUT << "TRADE WARNING: Client received trade invitation decision, but was not waiting for it";
	}
}

void TradeWidget::rejectAllPreviousInvitations() {
	for (std::list<trade_invitation_data>::const_iterator it = invitations_.begin(); it != invitations_.end(); ++it) {
		emit decideTradeInvitationSignal(it->hostFortressId, it->invitedFortressId, false);
	}

	invitations_.clear();
}
	
void TradeWidget::receiveTradeInvitation(const trade_invitation_data & invitation) {
	if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {
		// We sent invitation but before other player accepted it, we received another invitation

		if (invitation.hostFortressId ==  ui_->enemyPartner->getFortressId()) {
			rejectAllPreviousInvitations();
			// We sent invitation to some player and the same player invited us too, so we can automatically accept his invitation
			emit decideTradeInvitationSignal(invitation.hostFortressId, invitation.invitedFortressId, true);
		}
		else {
			// We sent invitation to another player than the one that is inviting us now, so show invitation dialog
			invitations_.push_back(invitation);
			showTradeInvitationDialog(invitation);
		}
	}
	else {
		invitations_.push_back(invitation);
		showTradeInvitationDialog(invitation);
	}
}

void TradeWidget::showTradeInvitationDialog(const trade_invitation_data & invitation) {
	if (tradeInvitationDialog_ == NULL) {
		createTradeInvitationDialog();
	}

	emit showDialogSignal();

	tradeInvitationDialog_->setDialog(invitation, false);

	tradeInvitationDialog_->show();
	tradeInvitationDialog_->raise();
	tradeInvitationDialog_->activateWindow();
}

void TradeWidget::cancelTradeInvitationDialogSlot() {
	if (!tradeInvitationDialog_->isTradeCanceled()) {
		// It could happen, that host canceled our invitation, so canceling invitation dialog in that case does not
		// send any cancelation to server. 

		// Do not change step, because we could be in any step when rejecting invitation or not in trade widget at all!

		if (currentStep_ == TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION) {			
			emit cancelTradeSignal();
		}		
		else if (currentStep_ == TRADE_STEP_INVITATION_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE) {
			emit cancelTradeSignal();
		}
		else {
			if (invitations_.size() > 0) {
				trade_invitation_data invitation = invitations_.front();
				invitations_.pop_front();

				emit decideTradeInvitationSignal(invitation.hostFortressId, invitation.invitedFortressId, false);
			}
		}
	}
	
	emit hideDialogSignal();
	tradeInvitationDialog_->close();
}

void TradeWidget::submitTradeInvitationDialogSlot() {
	if (invitations_.size() < 1) {
		emit hideDialogSignal();
		tradeInvitationDialog_->close();	
		KODIAK_DEBUG_COUT << "There is no invitation when accepting invitation dialog";
	}

	trade_invitation_data invitation = invitations_.front();
	invitations_.pop_front();

	rejectAllPreviousInvitations();

	if (tradeInvitationDialog_->isVisible()) {
		emit hideDialogSignal();
		tradeInvitationDialog_->close();
	}

	changeStep(TRADE_STEP_INVITATION_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE);

	ui_->selfPartner->setPartner(invitation.invitedFortressId, invitation.invitedFortressName, 
		invitation.invitedName, true, invitation.invitedIsShip);

	ui_->enemyPartner->setPartner(invitation.hostFortressId, invitation.hostFortressName, 
		invitation.hostName, false, invitation.hostIsShip);
	
	// This will also cancel current trade on server, if any
	emit decideTradeInvitationSignal(invitation.hostFortressId, invitation.invitedFortressId, true);
	emit hideDialogSignal();
	tradeInvitationDialog_->close();	
}

void TradeWidget::postponeTradeInvitationDialogSlot() {
	emit hideDialogSignal();
	tradeInvitationDialog_->close();
}

void TradeWidget::answerCancelTrade(id_t ownedFortressId, id_t partnerFortressId, const std::string & reason, const std::string & tradeRole) {
	switch (currentStep_) {
	case TRADE_STEP_OFFER_ITEMS:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			showMessageDialog(L"Ukončení obchodu", L"Server potvrdil tvou žádost o zrušení obchodu. Obchodování bylo zrušeno.", GAME_ICON_TRADE);
		}
		break;
	case TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			tradeInvitationDialog_->setAsSelfCanceled();
		}
		break;
	case TRADE_STEP_INVITATION_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			tradeInvitationDialog_->setAsSelfCanceled();
		}
		break;
	default:
		stepSelectYourFortress(true);
		showMessageDialog(L"Ukončení obchodu", L"Server potvrdil tvou žádost o zrušení obchodu. Obchodování bylo zrušeno.", GAME_ICON_TRADE);
	}

	this->tradeRole_ = tradeRole;
}

void TradeWidget::showMessageDialog(const std::wstring & title, const std::wstring & message, const std::string & iconKey) {
	if (messageDialog_ == NULL) {
		createMessageDialog();
	}

	emit showDialogSignal();

	messageDialog_->setTitle(title);
	messageDialog_->setMessage(message);
	messageDialog_->setIcon(iconKey);
	messageDialog_->setReason(L"");
	messageDialog_->setSuccess(true);

	messageDialog_->show();
	messageDialog_->raise();
	messageDialog_->activateWindow();
}

void TradeWidget::submitMessageDialogSlot() {
	emit hideDialogSignal();
	messageDialog_->close();
}

void TradeWidget::stepSelectYourFortress(bool reloadData) {
	this->commitRole_ = TRADE_COMMIT_ROLE_NONE;

	setActiveStep(ui_->step1Label);
	ui_->submitButton->setEnabled(false);
	ui_->cancelButton->setEnabled(false);
	ui_->currentDescriptionLabel->setText(stepSelectOwnedFortress_);

	ownedSecondFortressesTable_->clearAllContent();
	enemyFortressesTable_->clearAllContent();

	ui_->stackedWidget->setCurrentWidget(ui_->fortressTablePage);

	ui_->selfPartner->setNone();
	ui_->enemyPartner->setNone();

	ui_->tradeWithSpaceButton->setEnabled(false);

	changeStep(TRADE_STEP_SELECT_SELF_FORTRESS);

	if (reloadData) {
		emit ownedFortressesSignal();
	}
}

bool TradeWidget::matchesSelectedPartners(id_t ownedFortressId, id_t partnerFortressId) {
	return (ui_->selfPartner->getFortressId() == ownedFortressId && ui_->enemyPartner->getFortressId() == partnerFortressId);
}

void TradeWidget::removeMatchedInvitations(id_t ownedFortressId, id_t partnerFortressId) {
	// Remove canceled invitations

	std::list<trade_invitation_data>::iterator it = invitations_.begin();

	while (it != invitations_.end()) {
		if ((it->invitedFortressId == ownedFortressId && it->hostFortressId == partnerFortressId)) {
			it = invitations_.erase(it);
		}

		++it;
	}

	if (tradeInvitationDialog_->isVisible()) {
		if (tradeInvitationDialog_->getInvitation().invitedFortressId == ownedFortressId &&
			tradeInvitationDialog_->getInvitation().hostFortressId == partnerFortressId) {
				tradeInvitationDialog_->setAsPartnerCanceled();
		}
	}
}

void TradeWidget::receiveTradeCancelation(id_t ownedFortressId, id_t partnerFortressId) {
	switch (currentStep_) {
	case TRADE_STEP_OFFER_ITEMS:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			showMessageDialog(L"Ukončení obchodu", L"Obchodování bylo zrušeno druhým hráčem.", GAME_ICON_TRADE);
		}
		else {
			removeMatchedInvitations(ownedFortressId, partnerFortressId);
		}
		break;
	case TRADE_STEP_INVITATION_SENT_WAITING_FOR_PARTNER_DECISION:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			tradeInvitationDialog_->setAsPartnerRejected();
			changeStep(TRADE_STEP_BEFORE_SEND_INVITATION);
		}
		else {
			removeMatchedInvitations(ownedFortressId, partnerFortressId);
		}
		break;
	case TRADE_STEP_INVITATION_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			tradeInvitationDialog_->setAsPartnerCanceled();
		}
		else {
			removeMatchedInvitations(ownedFortressId, partnerFortressId);
		}
		break;
	case TRADE_STEP_COMMIT_SENT_WAITING_FOR_PARTNER_DECISION:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			emit showDialogSignal();
			commitDialog_->setAsDoneFailure(L"Hráči mají rozdílný pohled na nabídky");
		}
		else {
			removeMatchedInvitations(ownedFortressId, partnerFortressId);
		}
		break;
	case TRADE_STEP_COMMIT_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			emit showDialogSignal();
			commitDialog_->setAsDoneFailure(L"Hráči mají rozdílný pohled na nabídky");
		}
		else {
			removeMatchedInvitations(ownedFortressId, partnerFortressId);
		}
		break;
	case TRADE_STEP_COMMIT_RECEIVED_WAITING_FOR_SELF_DECISION:
		if (matchesSelectedPartners(ownedFortressId, partnerFortressId)) {
			stepSelectYourFortress(true);
			emit showDialogSignal();
			commitDialog_->setAsDoneFailure(L"Hráči mají rozdílný pohled na nabídky");
		}
		else {
			removeMatchedInvitations(ownedFortressId, partnerFortressId);
		}
		break;
	default:
		removeMatchedInvitations(ownedFortressId, partnerFortressId);
	}
}

void TradeWidget::rejectDialogSlot() {
	emit hideDialogSignal();
}

void TradeWidget::createTradeInvitationDialog() {
	tradeInvitationDialog_ = new TradeInvitationDialog(this);
		
	bool connected = true;		
	connected = connected && connect(tradeInvitationDialog_, SIGNAL(cancelSignal()), this, SLOT(cancelTradeInvitationDialogSlot()));
	connected = connected && connect(tradeInvitationDialog_, SIGNAL(submitSignal()), this, SLOT(submitTradeInvitationDialogSlot()));
	connected = connected && connect(tradeInvitationDialog_, SIGNAL(rejected()), this, SLOT(rejectDialogSlot()));
	connected = connected && connect(tradeInvitationDialog_, SIGNAL(postponeSignal()), this, SLOT(postponeTradeInvitationDialogSlot()));
	assert(connected && "Signals not connected");

	tradeInvitationDialog_->setWindowFlags(Qt::SplashScreen);
}

void TradeWidget::createMessageDialog() {
	messageDialog_ = new MessageDialog(this);
		
	bool connected = true;		
	connected = connected && connect(messageDialog_, SIGNAL(submitSignal()), this, SLOT(submitMessageDialogSlot()));
	connected = connected && connect(messageDialog_, SIGNAL(rejected()), this, SLOT(rejectDialogSlot()));
	assert(connected && "Signals not connected");

	messageDialog_->setWindowFlags(Qt::SplashScreen);
}

void TradeWidget::answerMoveTradeItem(const trade_movement_data & tradeData, bool isAuthor) {
	if (currentStep_ != TRADE_STEP_OFFER_ITEMS) {
		KODIAK_DEBUG_COUT << "Server sent item movement, but user is not trading";		
		return;
	}

	std::string realTradeDirection;

	if (isAuthor) {
		realTradeDirection = tradeData.tradeDirection;
	}
	else {
		if (tradeData.tradeDirection == TRADE_DIRECTION_OWNED_OFFER) {
			realTradeDirection = TRADE_DIRECTION_PARTNER_OFFER;
		}
		else if (tradeData.tradeDirection == TRADE_DIRECTION_OWNED_ITEMS) {
			realTradeDirection = TRADE_DIRECTION_PARTNER_ITEMS;
		}
		else if (tradeData.tradeDirection == TRADE_DIRECTION_PARTNER_OFFER) {
			realTradeDirection = TRADE_DIRECTION_OWNED_OFFER;
		}
		else if (tradeData.tradeDirection == TRADE_DIRECTION_PARTNER_ITEMS) {
			realTradeDirection = TRADE_DIRECTION_OWNED_ITEMS;
		}
	}

	if (realTradeDirection == TRADE_DIRECTION_OWNED_OFFER) {
		moveItemFromTableToTable(tradeData.item.id, ownedItemsTable_, ownedOfferTable_, tradeData.item.working, tradeData.item.damaged);
	}
	else if (realTradeDirection == TRADE_DIRECTION_OWNED_ITEMS) {
		moveItemFromTableToTable(tradeData.item.id, ownedOfferTable_, ownedItemsTable_, tradeData.item.working, tradeData.item.damaged);
	}
	else if (realTradeDirection == TRADE_DIRECTION_PARTNER_OFFER) {					
		if (tradeRole_ == PROTOCOL_TRADE_ROLE_SELF_TRADER || tradeRole_ == PROTOCOL_TRADE_ROLE_LOOT_TRADER) {			
			// If user is self trader or loot trader, than he has and can see items in partner table
			moveItemFromTableToTable(tradeData.item.id, enemyItemsTable_, enemyOfferTable_, tradeData.item.working, tradeData.item.damaged);
		}
		else {
			// Done. User cannot see partner items, so just remove it from partner offer.
			TradeItem * item = new TradeItem(tradeData.item);			
			moveItemTo(enemyOfferTable_, item);		
		}
	}
	else if (realTradeDirection == TRADE_DIRECTION_PARTNER_ITEMS) {					
		if (tradeRole_ == PROTOCOL_TRADE_ROLE_SELF_TRADER || tradeRole_ == PROTOCOL_TRADE_ROLE_LOOT_TRADER) {			
			// If user is self trader or loot trader, than he has and can see items in partner table
			moveItemFromTableToTable(tradeData.item.id, enemyOfferTable_, enemyItemsTable_, tradeData.item.working, tradeData.item.damaged);
		}
		else {
			// Done. User cannot see partner items, so just remove it from partner offer.
			moveItemFromTableAndDeleteSplit(tradeData, enemyOfferTable_);			
		}
	}
}

void TradeWidget::commitTrade(unsigned long selfFortressId, unsigned long partnerFortressId, ETradingResult result) {
	switch (result) {
	case TR_DONE:
		emit showDialogSignal();
		commitDialog_->setAsDoneSuccess();
		stepSelectYourFortress(true);
		break;
	case TR_FIRST_FORTRESS_NOT_STORING_ITEMS:		
		stepSelectYourFortress(true);
		emit showDialogSignal();
		commitDialog_->setAsDoneFailure(Settings::instance().getGameName(tradingResultToString(result)));
		break;
	case TR_SECOND_FORTRESS_NOT_STORING_ITEMS:		
		stepSelectYourFortress(true);
		emit showDialogSignal();
		commitDialog_->setAsDoneFailure(Settings::instance().getGameName(tradingResultToString(result)));
		break;
	case TR_NOT_IN_RANGE:		
		stepSelectYourFortress(true);
		emit showDialogSignal();
		commitDialog_->setAsDoneFailure(Settings::instance().getGameName(tradingResultToString(result)));
		break;
	default:
		changeStep(TRADE_STEP_OFFER_ITEMS);

		setActiveStep(ui_->step4Label);

		if (tradeRole_ == PROTOCOL_TRADE_ROLE_PARTNER_TRADER) {
			ui_->currentDescriptionLabel->setText(partnerTradeStep_);
		}
		else {
			ui_->currentDescriptionLabel->setText(selfTradeStep_);
		}

		emit showDialogSignal();
		commitDialog_->setAsDoneFailure(Settings::instance().getGameName(tradingResultToString(result)));
	}
}

void TradeWidget::prepareCommitTrade(unsigned long selfFortressId, unsigned long partnerFortressId, ETradingCommitRole commitRole) {

	this->commitRole_ = commitRole;

	switch (commitRole) {
	case TRADE_COMMIT_ROLE_HOST:
		changeStep(TRADE_STEP_COMMIT_SENT_WAITING_FOR_PARTNER_DECISION);
		emit showDialogSignal();
		commitDialog_->setAsWaitForPartnerDecision();
		break;
	case TRADE_COMMIT_ROLE_INVITED:
		changeStep(TRADE_STEP_COMMIT_RECEIVED_WAITING_FOR_SELF_DECISION);	
		emit showDialogSignal();
		commitDialog_->setAsInvitation();

		ui_->currentDescriptionLabel->setText(stepCommitTrade_);
		setActiveStep(ui_->step5Label);

		break;
	}
}

void TradeWidget::signalCommitTrade() {
	client_trade_data selfOffer;

	selfOffer.deuterium = ui_->ownedDeuteriumSlider->getValue();
	selfOffer.energy = ui_->ownedEnergySlider->getValue();
	selfOffer.heavyWater = ui_->ownedHeavyWaterSlider->getValue();
	selfOffer.ilmenite = ui_->ownedIlmeniteSlider->getValue();
	selfOffer.quarkGluonPlasma = ui_->ownedPlasmaSlider->getValue();
	selfOffer.titanium = ui_->ownedTitanSlider->getValue();
	selfOffer.ulrea = ui_->ownedUlreaSlider->getValue();
	selfOffer.zirconiumCrystal = ui_->ownedCrystalsSlider->getValue();

	for (std::map<id_t, TradeItem *>::const_iterator it = ownedOfferTable_->storageBegin(); it != ownedOfferTable_->storageEnd(); ++it) {
		client_trade_item_data itemData;

		itemData.id = it->second->getWarehouseItem().id;
		itemData.working = it->second->getWarehouseItem().working;
		itemData.damaged = it->second->getWarehouseItem().damaged;

		selfOffer.tradeItems.push_back(itemData);
	}

	client_trade_data partnerOffer;

	partnerOffer.deuterium = partnerResources_.deuterium;
	partnerOffer.energy = partnerResources_.energy;
	partnerOffer.heavyWater = partnerResources_.heavyWater;
	partnerOffer.ilmenite = partnerResources_.ilmenite;
	partnerOffer.quarkGluonPlasma = partnerResources_.quarkGluonPlasma;
	partnerOffer.titanium = partnerResources_.titanium;
	partnerOffer.ulrea = partnerResources_.ulrea;
	partnerOffer.zirconiumCrystal = partnerResources_.zirconiumCrystal;

	for (std::map<id_t, TradeItem *>::const_iterator it = enemyOfferTable_->storageBegin(); it != enemyOfferTable_->storageEnd(); ++it) {
		client_trade_item_data itemData;

		itemData.id = it->second->getWarehouseItem().id;
		itemData.working = it->second->getWarehouseItem().working;
		itemData.damaged = it->second->getWarehouseItem().damaged;

		partnerOffer.tradeItems.push_back(itemData);
	}

	changeStep(TRADE_STEP_COMMIT_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE);

	emit commitTradeSignal(ui_->selfPartner->getFortressId(), ui_->enemyPartner->getFortressId(), selfOffer, partnerOffer);
}

void TradeWidget::answerMoveTradeResource(const trade_resource_movement_data & tradeData, bool isAuthor) {
	if (currentStep_ != TRADE_STEP_OFFER_ITEMS) {
		KODIAK_DEBUG_COUT << "Server sent item movement, but user is not trading";		
		return;
	}

	isSynchronizing_ = true;

	std::string realTradeDirection;

	if (isAuthor) {
		realTradeDirection = tradeData.tradeDirection;
	}
	else {
		if (tradeData.tradeDirection == TRADE_DIRECTION_OWNED_OFFER) {
			realTradeDirection = TRADE_DIRECTION_PARTNER_OFFER;
		}
		else if (tradeData.tradeDirection == TRADE_DIRECTION_PARTNER_OFFER) {
			realTradeDirection = TRADE_DIRECTION_OWNED_OFFER;
		}
	}

	if (realTradeDirection == TRADE_DIRECTION_OWNED_OFFER) {
		switch (tradeData.resourceType) {
		case GAME_RESOURCE_TYPE_DEUTERIUM: 
			ui_->ownedDeuteriumSlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_ENERGY:
			ui_->ownedEnergySlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_HEAVY_WATER:
			ui_->ownedHeavyWaterSlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_ILMENITE:
			ui_->ownedIlmeniteSlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_QUARK_GLUON_PLASMA:
			ui_->ownedPlasmaSlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_TITANIUM:
			ui_->ownedTitanSlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_ULREA:
			ui_->ownedUlreaSlider->setValue(tradeData.count);
			break;
		case GAME_RESOURCE_TYPE_ZIRCONIUM_CRYSTALS:
			ui_->ownedCrystalsSlider->setValue(tradeData.count);
			break;
		}
	}
	else if (realTradeDirection == TRADE_DIRECTION_PARTNER_OFFER) {			
		if (tradeRole_ == PROTOCOL_TRADE_ROLE_SELF_TRADER || tradeRole_ == PROTOCOL_TRADE_ROLE_LOOT_TRADER) {
			switch (tradeData.resourceType) {
			case GAME_RESOURCE_TYPE_DEUTERIUM: 
				ui_->enemyDeuteriumSlider->setValue(tradeData.count);
				partnerResources_.deuterium = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ENERGY:
				ui_->enemyEnergySlider->setValue(tradeData.count);
				partnerResources_.energy = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_HEAVY_WATER:
				ui_->enemyHeavyWaterSlider->setValue(tradeData.count);
				partnerResources_.heavyWater = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ILMENITE:
				ui_->enemyIlmeniteSlider->setValue(tradeData.count);
				partnerResources_.ilmenite = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_QUARK_GLUON_PLASMA:
				ui_->enemyPlasmaSlider->setValue(tradeData.count);
				partnerResources_.quarkGluonPlasma = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_TITANIUM:
				ui_->enemyTitanSlider->setValue(tradeData.count);
				partnerResources_.titanium = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ULREA:
				ui_->enemyUlreaSlider->setValue(tradeData.count);
				partnerResources_.ulrea = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ZIRCONIUM_CRYSTALS:
				ui_->enemyCrystalsSlider->setValue(tradeData.count);
				partnerResources_.zirconiumCrystal = tradeData.count;
				break;
			}
		}
		else {
			switch (tradeData.resourceType) {
			case GAME_RESOURCE_TYPE_DEUTERIUM: 
				ui_->enemyDeuteriumValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.deuterium = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ENERGY:
				ui_->enemyEnergyValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.energy = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_HEAVY_WATER:
				ui_->enemyHeavyWaterValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.heavyWater = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ILMENITE:
				ui_->enemyIlmeniteValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.ilmenite = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_QUARK_GLUON_PLASMA:
				ui_->enemyPlasmaValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.quarkGluonPlasma = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_TITANIUM:
				ui_->enemyTitanValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.titanium = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ULREA:
				ui_->enemyUlreaValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.ulrea = tradeData.count;
				break;
			case GAME_RESOURCE_TYPE_ZIRCONIUM_CRYSTALS:
				ui_->enemyCrystalsValue->setText(Settings::instance().formatNumber(tradeData.count));
				partnerResources_.zirconiumCrystal = tradeData.count;
				break;
			}
		}
	}

	isSynchronizing_ = false;
}

void TradeWidget::createCommitDialog() {
	commitDialog_ = new CommitDialog(this);
		
	bool connected = true;		
	connected = connected && connect(commitDialog_, SIGNAL(submitSignal()), this, SLOT(submitCommitInvitationDialogSlot()));
	connected = connected && connect(commitDialog_, SIGNAL(cancelSignal()), this, SLOT(cancelCommitInvitationDialogSlot()));
	connected = connected && connect(commitDialog_, SIGNAL(rejected()), this, SLOT(rejectDialogSlot()));
	assert(connected && "Signals not connected");

	commitDialog_->setWindowFlags(Qt::SplashScreen);
}

void TradeWidget::submitCommitInvitationDialogSlot() {
	if (currentStep_ == TRADE_STEP_COMMIT_RECEIVED_WAITING_FOR_SELF_DECISION) {
		emit showDialogSignal();
		commitDialog_->setAsWaitForAcceptResponse();
		signalCommitTrade();	
	}
	else {
		emit hideDialogSignal();
		commitDialog_->close();
	}
}

void TradeWidget::cancelCommitInvitationDialogSlot() {
	if (currentStep_ == TRADE_STEP_COMMIT_RECEIVED_WAITING_FOR_SELF_DECISION) {
		emit showDialogSignal();
		commitDialog_->setAsWaitForRejectResponse();
		changeStep(TRADE_STEP_COMMIT_DECISION_SENT_WAITING_FOR_SERVER_RESPONSE);
		emit cancelTradeCommitSignal(ui_->selfPartner->getFortressId(), ui_->enemyPartner->getFortressId());
	}
	else {
		emit hideDialogSignal();
		commitDialog_->close();
	}
}

void TradeWidget::answerCancelTradeCommit(id_t selfFortressId, id_t partnerFortressId, const std::string & reason) {
	if (commitRole_ == TRADE_COMMIT_ROLE_INVITED) {
		this->commitRole_ = TRADE_COMMIT_ROLE_NONE;

		changeStep(TRADE_STEP_OFFER_ITEMS);
		emit hideDialogSignal();
		commitDialog_->close();
	}
	else if (commitRole_ == TRADE_COMMIT_ROLE_HOST) {
		changeStep(TRADE_STEP_OFFER_ITEMS);
		emit showDialogSignal();
		commitDialog_->setAsPartnerRejected();
	}
	else {
		emit hideDialogSignal();
		commitDialog_->close();
	}
}

void TradeWidget::signalMoveOwnedTradeResource(game_resource_type resourceType, unsigned long long value) {
	trade_resource_movement_data data;
	data.count = value;
	data.selfFortressId = ui_->selfPartner->getFortressId();
	data.partnerFortressId = ui_->enemyPartner->getFortressId();
	data.resourceType = resourceType;
	data.tradeDirection = TRADE_DIRECTION_OWNED_OFFER;

	emit moveTradeResourceSignal(data);
}

void TradeWidget::signalMovePartnerTradeResource(game_resource_type resourceType, unsigned long long value) {
	trade_resource_movement_data data;
	data.count = value;
	data.selfFortressId = ui_->selfPartner->getFortressId();
	data.partnerFortressId = ui_->enemyPartner->getFortressId();
	data.resourceType = resourceType;
	data.tradeDirection = TRADE_DIRECTION_PARTNER_OFFER;

	emit moveTradeResourceSignal(data);
}

void TradeWidget::ownedDeuteriumChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_DEUTERIUM, value);
}

void TradeWidget::ownedEnergyChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_ENERGY, value);
}

void TradeWidget::ownedHeavyWaterChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_HEAVY_WATER, value);
}

void TradeWidget::ownedIlmeniteChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_ILMENITE, value);
}

void TradeWidget::ownedPlasmaChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_QUARK_GLUON_PLASMA, value);
}

void TradeWidget::ownedTitanChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_TITANIUM, value);
}

void TradeWidget::ownedUlreaChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_ULREA, value);
}

void TradeWidget::ownedCrystalsChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMoveOwnedTradeResource(GAME_RESOURCE_TYPE_ZIRCONIUM_CRYSTALS, value);
}

void TradeWidget::enemyDeuteriumChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_DEUTERIUM, value);
}

void TradeWidget::enemyEnergyChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_ENERGY, value);
}

void TradeWidget::enemyHeavyWaterChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_HEAVY_WATER, value);
}

void TradeWidget::enemyIlmeniteChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_ILMENITE, value);
}

void TradeWidget::enemyPlasmaChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_QUARK_GLUON_PLASMA, value);
}

void TradeWidget::enemyTitanChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_TITANIUM, value);
}

void TradeWidget::enemyUlreaChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_ULREA, value);
}

void TradeWidget::enemyCrystalsChangedSlot(unsigned long long value) {
	if (isSynchronizing_) { return; }
	signalMovePartnerTradeResource(GAME_RESOURCE_TYPE_ZIRCONIUM_CRYSTALS, value);
}


void TradeWidget::clearState() {
	ownedFortressesTable_->clearAllContent();
	enemyFortressesTable_->clearAllContent();
	ownedItemsTable_->clearAllContent();
	enemyItemsTable_->clearAllContent();

	stepSelectYourFortress(true);
}