#include "fightWidget.h"
#include <cassert>
#include "softProj\settings.h"
#include "fightWidgetRow.h"
#include "../../streams/ErrorStream.h"
#include <qstringbuilder.h>

extern KODIAK_DEBUG_STREAM KODIAK_DEBUG_COUT;

FightWidget::FightWidget(QWidget *parent) : NotifyWidget(parent) {
    ui_.setupUi(this);

	isSynchronizing_ = false;

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

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

	setNoEnemyPartner();
	setNoSelfPartner();
	setNoPreparedPartner();

	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 && QObject::connect(ui_.weaponsWidget, SIGNAL(submitWeaponsSignal(WeaponsChangeDetails &)),
		this, SLOT(submitWeaponsSlot(WeaponsChangeDetails &)));

	connected = connected && QObject::connect(ui_.weaponsWidget, SIGNAL(resetWeaponsSignal()),
		this, SLOT(resetWeaponsSlot()));

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

	ui_.weaponsWidget->setAsSmall();
	ui_.weaponsWidget->setVisible(false);
	ui_.shieldsCopySlider->showCurrent(false);
	ui_.shieldsCopySlider->showMaximum(false);
	ui_.shieldsSlider->setUnit(L"TJ");

	ui_.slidersStackedWidget->setCurrentWidget(ui_.infoPage);
}

void FightWidget::updateFortressFightData(const fortress_detailed_fight_data & fightData) {
	// Set sliders only if it is the same fortress as selected
	if (ui_.selfPartner->getFortressId() != fightData.id) {
		return;
	}

	this->fightData_ = fightData;
	rememberUpdateTime();

	ui_.integritySlider->setMinimum(0);
	ui_.integritySlider->setMaximum(fightData.totalStructuralIntegrity);
	ui_.integritySlider->setValue(fightData.actualStructuralIntegrity);

	ui_.shieldsCopySlider->setMinimum(0);
	ui_.shieldsCopySlider->setMaximum(fightData.shieldsClientAccumulator);
	ui_.shieldsCopySlider->setValue(fightData.shieldsActualAccumulator);

	ui_.shieldsSlider->setMinimum(0);
	ui_.shieldsSlider->setMaximum(fightData.shieldsClientAccumulator);
	ui_.shieldsSlider->setValue(fightData.shieldsEnergy);

	ui_.slidersStackedWidget->setCurrentWidget(ui_.slidersPage);
}

void FightWidget::setOwnedFortresses(const std::vector<fortress_attack_information> & items) {
    clearAllOwnedFortresses();
	// Do not clear enemy table

	// Clear old attacking enemies information, it will be updated
	allAttackingEnemyReports_.clear();
	allAttackingEnemyReportsByTargetFortress_.clear();
	selfUnderAttackReportsList_.clear();

	FightWidgetRowWidget * clickedRow = ownedFortressesTable_->getClickedRow();

	bool isPreviouslySelectedRowStillPresent = false;
	std::set<id_t> attackersOnSelectedFortress;
	id_t selectedID = getSelectedOwnedFortressID();

    for (std::vector<fortress_attack_information>::const_iterator it = items.begin(); it != items.end(); ++it) {
		FightWidgetRow * widget = new FightWidgetRow(*it, (EFortressType) it->fortressFightData.type, true);
		widget->setShellIconEnabled(false);

		FightWidgetRowWidget * rowWidget = insertOwnedFortress(widget);	
		
		id_t ownedID = it->fortressFightData.id;
		id_t enemyID = it->fortressInWeaponsTargetId;		

		if (enemyID != 0) {
			allAttackingEnemyReports_[ownedID] = enemyID;
			allAttackingEnemyReportsByTargetFortress_[enemyID].insert(ownedID);
		}

		for (std::list<id_t>::const_iterator attackerIt = it->attackers.begin(); attackerIt != it->attackers.end(); ++attackerIt) {
			allAttackingEnemyReports_[*attackerIt] = ownedID;
			allAttackingEnemyReportsByTargetFortress_[ownedID].insert(*attackerIt);
		}

		// If is attacking
		if (enemyID != 0) {
			fight_enemy_data enemyData;
			attackInformationToFightEnemyData(*it, enemyData);
			attackingSelfReports_[ownedID] = enemyData;	
		}
		else {
			attackingSelfReports_.erase(ownedID);
		}

		// Check for match with previously selected row

		if (clickedRow != NULL) {
			// If there is previously selected row that represents fortress with the ID that is present in new 
			// set, then we want to keep its enemy table and icons in that table
			if (clickedRow->getItemId() == ownedID) {
				isPreviouslySelectedRowStillPresent = true;
			}
		}

		fortress_under_attack_data data;
		data.fortressID = it->fortressFightData.id;
		data.fortressName = it->fortressFightData.name;
		data.attackerCount = 0;

		selfUnderAttackReportsList_[data.fortressID] = data;
    }

	if (isPreviouslySelectedRowStillPresent && selectedID != 0) {
		refreshOwnedRowById(selectedID);

		const std::set<id_t> & attackersOnSelected = allAttackingEnemyReportsByTargetFortress_[selectedID];

		for (std::set<id_t>::const_iterator it = attackersOnSelected.begin(); it != attackersOnSelected.end(); ++it) {
			refreshOwnedRowById(*it);
			refreshEnemyRowById(*it);
		}
	}
	else {
		// If there is no match, we want to clear enemy table and unselect selected item, if any
		enemyFortressesTable_->clearAllContent();

		if (clickedRow != NULL) {
			ownedFortressesTable_->setNoRowAsClicked();
		}
	}

	refreshAllRows();

	updateSelfUnderAttackList();
}

void FightWidget::setEnemyFortresses(const fortress_attack_information & ownedFortressAttackData, const std::vector<SimpleItem> & ships, const std::vector<SimpleItem> & bases) {
    clearAllEnemyFortresses();

	id_t ownedID = ui_.selfPartner->getFortressId();

	if (ownedFortressAttackData.fortressFightData.id != ownedID) {
		return;
	}	

	updateFortressFightData(ownedFortressAttackData.fortressFightData);

    for (std::vector<SimpleItem>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
		if (it->id == ownedID) {
			continue;
		}

		FightWidgetRow * widget = new FightWidgetRow(*it, FORTRESS_TYPE_SHIP, false);
		widget->setShellIconEnabled(false);
		insertEnemyFortress(widget);	
    }

    for (std::vector<SimpleItem>::const_iterator it = bases.begin(); it != bases.end(); ++it) {
		if (it->id == ownedID) {
			continue;
		}

		FightWidgetRow * widget = new FightWidgetRow(*it, FORTRESS_TYPE_BASE, false);
		widget->setShellIconEnabled(false);
		insertEnemyFortress(widget);	
    }

	ui_.preparedPartner->setNone();
	ui_.submitButton->setEnabled(false);

	if (ownedFortressAttackData.fortressInWeaponsTargetId != 0) {
		ui_.enemyPartnerLabel->setText(QString::fromUtf16(L"Tvoje pevnost útočí na"));
		ui_.cancelButton->setEnabled(true);				
		ui_.enemyPartner->setPartner(ownedFortressAttackData.fortressInWeaponsTargetId, ownedFortressAttackData.fortressInWeaponsTargetName,
			ownedFortressAttackData.fortressInWeaponsRangeTargetRealmName, false, ((EFortressType) ownedFortressAttackData.fortressInWeaponsRangeTargetType) == FORTRESS_TYPE_SHIP);
	}
	else {
		setNoEnemyPartner();
	}

	refreshAllRows();
}

FightWidget::~FightWidget()
{
	delete ownedFortressesTable_;
	delete enemyFortressesTable_;

	allAttackingEnemyReportsByTargetFortress_.clear();
}

void FightWidget::ownedFortressClicked(FightWidgetRow * item, int row) {
	if (item == 0) { return; }

	setSelfPartner(item);	
	ui_.preparedPartner->setNone();
	ui_.submitButton->setEnabled(false);

	id_t ownedID = item->getId();

	bool isAttacking = allAttackingEnemyReports_.find(ownedID) != allAttackingEnemyReports_.end();

	if (isAttacking && (attackingSelfReports_.find(ownedID) != attackingSelfReports_.end())) {
		fight_enemy_data data = attackingSelfReports_[ownedID];
		setEnemyPartner(data);
	}
	else {
		setNoEnemyPartner();
	}

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

	refreshAllRows();

	emit fortressInWeaponsRangeSignal(item->getId());
	emit fortressWeaponsSettingsSignal(item->getId());	
}

void FightWidget::refreshAllRows() {
	int ownedRowCount = ui_.ownedFortressesTable->rowCount();

	for (int row = 0; row < ownedRowCount; ++row) {
		FightWidgetRowWidget * rowWidget = dynamic_cast<FightWidgetRowWidget*>(ui_.ownedFortressesTable->cellWidget(row, 0));

		if (rowWidget == NULL) {
			continue;
		}

		refreshRow(rowWidget);	
	}

	int enemyRowCount = ui_.enemyFortressesTable->rowCount();

	for (int row = 0; row < enemyRowCount; ++row) {
		FightWidgetRowWidget * rowWidget = dynamic_cast<FightWidgetRowWidget*>(ui_.enemyFortressesTable->cellWidget(row, 0));

		if (rowWidget == NULL) {
			continue;
		}

		refreshRow(rowWidget);	
	}
}

void FightWidget::ownedFortressDoubleClicked(FightWidgetRow * item, int row) {
	// Not interested, do nothing
}

void FightWidget::enemyFortressClicked(FightWidgetRow * item, int row) {
	enemyFortressesTable_->setRowAsClicked(row);

	setPreparedPartner(item);
	ui_.submitButton->setEnabled(true);	
	ui_.preparedPartnerLabel->setText(QString::fromUtf16(L"Nový vybraný cíl"));
}

void FightWidget::enemyFortressDoubleClicked(FightWidgetRow * item, int row) {
	emit attackFortressSignal(ui_.selfPartner->getFortressId(), item->getId());
}

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

void FightWidget::clearAllEnemyFortresses() {
	enemyFortressesTable_->clearAllContent();
}

FightWidgetRowWidget * FightWidget::insertOwnedFortress(FightWidgetRow * item) {
	return ownedFortressesTable_->insertItem(item);
}

FightWidgetRowWidget *  FightWidget::insertEnemyFortress(FightWidgetRow * item) {
	return enemyFortressesTable_->insertItem(item);
}

void FightWidget::setSelfPartner(FightWidgetRow * item) {
	ui_.selfPartner->setPartner(item->getId(), item->getName(), item->getRealmName(), item->isOwned(), item->isShip());
}

void FightWidget::setPreparedPartner(FightWidgetRow * item) {
	ui_.preparedPartner->setPartner(item->getId(), item->getName(), item->getRealmName(), item->isOwned(), item->isShip());
}

void FightWidget::updateWeaponsInformation(id_t fortressId, weapons_status & state) {
	ui_.weaponsWidget->setState(state);
	ui_.weaponsWidget->setVisible(true);
}

void FightWidget::submitButtonClickedSlot() {
	ui_.submitButton->setEnabled(false);
	emit attackFortressSignal(ui_.selfPartner->getFortressId(), ui_.preparedPartner->getFortressId());
}

void FightWidget::cancelButtonClickedSlot() {
	emit stopAttackFortressSignal(ui_.selfPartner->getFortressId());
}

void FightWidget::submitWeaponsSlot(WeaponsChangeDetails & state) {
	emit submitWeaponsSignal(ui_.selfPartner->getFortressId(), state);	
}

void FightWidget::resetWeaponsSlot() {
	emit resetWeaponsSignal(ui_.selfPartner->getFortressId());	
}

id_t FightWidget::getSelfFortressId() {
	return ui_.selfPartner->getFortressId();
}

QString printStrong(const std::string & text, bool spacePrefixIfNeccessary = false) {
	if (text != "") {
		if (spacePrefixIfNeccessary) {
			return " <strong>" + QString::fromUtf8(text.c_str()) + "</strong>";
		}
		else {
			return "<strong>" + QString::fromUtf8(text.c_str()) + "</strong>";
		}
	}
	else {
		return "";
	}	
}

QString printStrong(const std::wstring & text) {
	return "<strong>" + QString::fromUtf16(text.c_str()) + "</strong>";
}

QString printNormal(const std::wstring & text) {
	return QString::fromUtf16(text.c_str());
}

QString printRedNormal(const std::wstring & text) {
	return QString::fromUtf16(L"<span style=\"color: rgb(170, 45, 45);\">") % QString::fromUtf16(text.c_str()) % QString::fromUtf16(L"</span>");
}

QString printGreenNormal(const std::wstring & text) {
	return QString::fromUtf16(L"<span style=\"color: rgb(110, 155, 80);\">") % QString::fromUtf16(text.c_str()) % QString::fromUtf16(L"</span>");
}

QString printGreenHeader(const std::wstring & text) {
	return QString::fromUtf16(L"<h2 style=\"color: rgb(110, 155, 80); margin-bottom: 2px; margin-top: 2px;\">") % QString::fromUtf16(text.c_str()) % QString::fromUtf16(L"</h2>");
}

QString printRedHeader(const std::wstring & text) {
	return QString::fromUtf16(L"<h2 style=\"color: rgb(170, 45, 45); margin-bottom: 2px; margin-top: 2px;\">") % QString::fromUtf16(text.c_str()) % QString::fromUtf16(L"</h2>");
}

QString printBlueHeader(const std::wstring & text) {
	return QString::fromUtf16(L"<h3 style=\"color: rgb(75, 120, 175); margin-bottom: 2px; margin-top: 2px;\">") % QString::fromUtf16(text.c_str()) % QString::fromUtf16(L"</h3>");
}

QString printNewLine() {
	return "<br />";
}

QString printNumber(unsigned long long number) {
	return Settings::instance().formatNumber(number);
}

QString printStrongNumber(unsigned long long number) {
	return "<strong>" % Settings::instance().formatNumber(number) % "</strong>";
}

QString printPercents(double number) {
	return QString::number(number) % " %";
}

QString printStrongPercents(double number) {
	return "<strong>" % QString::number(number) % " %</strong>";
}

void FightWidget::updateSelfUnderAttackList() {
	for (std::map<id_t, fortress_under_attack_data>::iterator it = selfUnderAttackReportsList_.begin(); it != selfUnderAttackReportsList_.end(); ++it) {
		it->second.attackerCount = allAttackingEnemyReportsByTargetFortress_[it->second.fortressID].size();
	}

	emit updateAttackWarningsSignal(selfUnderAttackReportsList_);
}

void FightWidget::fightActionReport(const fight_action_report & report) {

	switch (report.action) {
		case FIGHT_ACTION_OUR_WEAPONS_LOCKED_ON_ENEMY:
		{
			QString message;

			message =
				printGreenHeader(L"Zaměřil jsi zbraně na nepřítele!")
				% printNormal(L"Tvoje pevnost")
				% printStrong(report.selfFortressName, true) 
				% printNormal(L" zaměřila zbraně na pevnost")
				% printStrong(report.enemyFortressName, true)
				% printNormal(L" hráče" )
				% printStrong(report.enemyRealmName, true)
				% printNewLine();

			if (ui_.selfPartner->getFortressId() == report.selfFortressId) {
				setEnemyPartner(report);
			}

			if (ui_.preparedPartner->getFortressId() == report.enemyFortressId) {
				setNoPreparedPartner();
			}

			allAttackingEnemyReports_[report.selfFortressId] = report.enemyFortressId;
			allAttackingEnemyReportsByTargetFortress_[report.enemyFortressId].insert(report.selfFortressId);

			refreshRows(report.selfFortressId, report.enemyFortressId, 0);	

			updateSelfUnderAttackList();

			ui_.textBrowser->append(message);
			break;
		}		
		case FIGHT_ACTION_OUR_WEAPONS_UNLOCKED:
		{
			QString message;

			message =
			printGreenHeader(L"Zrušil jsi útok na nepřítele!")
				% printNormal(L"Tvoje pevnost")
				% printStrong(report.selfFortressName, true) 
				% printNormal(L" zrušila útok na pevnost")
				% printStrong(report.enemyFortressName, true)
				% printNormal(L" hráče" )
				% printStrong(report.enemyRealmName, true)
				% printNewLine();

			if (ui_.selfPartner->getFortressId() == report.selfFortressId) {
				setNoEnemyPartner();
			}

			id_t selfTargetID = allAttackingEnemyReports_[report.selfFortressId];

			allAttackingEnemyReports_.erase(report.selfFortressId);
			allAttackingEnemyReportsByTargetFortress_[selfTargetID].erase(report.selfFortressId);

			refreshRows(report.selfFortressId, report.enemyFortressId, selfTargetID);	

			updateSelfUnderAttackList();

			ui_.textBrowser->append(message);
			break;
		}
		case FIGHT_ACTION_ENEMY_WEAPONS_LOCKED_ON_WARNING:
		{
			QString message;

			message =
			printRedHeader(L"Nepřátelská pevnost na tebe útočí!")
				% printNormal(L"Nepřátelská pevnost")
				% printStrong(report.enemyFortressName, true) 
				% printNormal(L" hráče" )
				% printStrong(report.enemyRealmName, true)
				% printNormal(L" zaměřila zbraně na tvou pevnost")
				% printStrong(report.selfFortressName, true)
				% printNewLine();

			allAttackingEnemyReports_[report.enemyFortressId] = report.selfFortressId;
			allAttackingEnemyReportsByTargetFortress_[report.selfFortressId].insert(report.enemyFortressId);

			refreshRows(report.selfFortressId, report.enemyFortressId, 0);	

			updateSelfUnderAttackList();

			ui_.textBrowser->append(message);
			break;
		}		
		case FIGHT_ACTION_ENEMY_WEAPONS_UNLOCKED:
		{
			QString message;
			message =
			printRedHeader(L"Nepřátelská pevnost zrušila útok!")
				% printNormal(L"Nepřátelská pevnost")
				% printStrong(report.enemyFortressName, true) 
				% printNormal(L" hráče" )
				% printStrong(report.enemyRealmName, true)
				% printNormal(L" zrušila útok na tvou pevnost")
				% printStrong(report.selfFortressName, true)
				% printNewLine();

			allAttackingEnemyReports_.erase(report.enemyFortressId);
			allAttackingEnemyReportsByTargetFortress_[report.selfFortressId].erase(report.enemyFortressId);

			refreshRows(report.selfFortressId, report.enemyFortressId, 0);	

			updateSelfUnderAttackList();

			ui_.textBrowser->append(message);			

			break;
		}		
		case FIGHT_ACTION_THIS_FORTRESS_HAS_BEEN_ANNIHILATED:
		{
			QString message =
				printRedHeader(L"Tvoje pevnost byla zničena!")
				% printNormal(L"Tvoje pevnost")
				% printStrong(report.selfFortressName, true) 
				% printNormal(L" byla zničena nepřátelskou pevností")
				% printStrong(report.enemyFortressName, true)
				% printNormal(L" hráče" )
				% printStrong(report.enemyRealmName, true)
				% printNewLine();

			if (ui_.selfPartner->getFortressId() == report.selfFortressId) {
				setNoSelfPartner();
				setNoEnemyPartner();
				setNoPreparedPartner();
			}

			unsetClickedItemInOwnedTableIfNeccessary(report.selfFortressId);

			// If fortress is in enemy table, delete it
			if (ownedFortressesTable_->findItemRow(report.enemyFortressId, 0) != NULL) {
				ownedFortressesTable_->removeRowAndItemById(report.enemyFortressId);				
			}

			// If fortress is in enemy table, delete it
			if (enemyFortressesTable_->findItemRow(report.enemyFortressId, 0) != NULL) {
				enemyFortressesTable_->removeRowAndItemById(report.enemyFortressId);				
			}

			id_t selfTargetID = allAttackingEnemyReports_[report.selfFortressId];

			// Destroyed self stop attacking at all
			allAttackingEnemyReports_.erase(report.selfFortressId);
			// Destroyed self stop attack its target
			allAttackingEnemyReportsByTargetFortress_[selfTargetID].erase(report.selfFortressId);

			// Enemy fortress stop attacking
			allAttackingEnemyReports_.erase(report.enemyFortressId);
			allAttackingEnemyReportsByTargetFortress_[report.selfFortressId].erase(report.enemyFortressId);

			refreshRows(report.selfFortressId, report.enemyFortressId, selfTargetID);		

			ui_.textBrowser->append(message);

			if (report.selfFortressId == getSelectedOwnedFortressID()) {
				ui_.slidersStackedWidget->setCurrentWidget(ui_.infoPage);
				ui_.weaponsWidget->setVisible(false);
			}

			selfUnderAttackReportsList_.erase(report.selfFortressId);
			updateSelfUnderAttackList();

			emit removeFortressSignal(report.selfFortressId, report.selfFortressName);
			break;
		}	
		case FIGHT_ACTION_WEAPONS_TARGET_HAS_BEEN_ANNIHILATED:
		{
			QString message =
				printGreenHeader(L"Zničil jsi nepřátelskou pevnost!")
				% printNormal(L"Tvoje pevnost")
				% printStrong(report.selfFortressName, true) 
				% printNormal(L" zničila nepřátelskou pevnost")
				% printStrong(report.enemyFortressName, true)
				% printNormal(L" hráče" )
				% printStrong(report.enemyRealmName, true)
				% printNewLine();

			if (report.enemyFortressId == ui_.enemyPartner->getFortressId()) {
				setNoEnemyPartner();
			}

			if (report.enemyFortressId == ui_.preparedPartner->getFortressId()) {
				setNoPreparedPartner();
			}

			if (report.enemyFortressId == getSelectedOwnedFortressID()) {
				ui_.slidersStackedWidget->setCurrentWidget(ui_.infoPage);
				ui_.weaponsWidget->setVisible(false);
			}

			// If fortress is in enemy table, delete it
			if (ownedFortressesTable_->findItemRow(report.enemyFortressId, 0) != NULL) {
				ownedFortressesTable_->removeRowAndItemById(report.enemyFortressId);				
			}

			// If fortress is in enemy table, delete it
			if (enemyFortressesTable_->findItemRow(report.enemyFortressId, 0) != NULL) {
				enemyFortressesTable_->removeRowAndItemById(report.enemyFortressId);				
			}

			unsetClickedItemInEnemyTableIfNeccessary(report.enemyFortressId);
			
			id_t enemyTargetID = allAttackingEnemyReports_[report.enemyFortressId];

			// Destroyed target stop attacking at all
			allAttackingEnemyReports_.erase(report.enemyFortressId);
			// Destroyed target stop attack its target
			allAttackingEnemyReportsByTargetFortress_[enemyTargetID].erase(report.enemyFortressId);

			// Our fortress that attacked stops attacking
			allAttackingEnemyReports_.erase(report.selfFortressId);
			allAttackingEnemyReportsByTargetFortress_[report.enemyFortressId].erase(report.selfFortressId);

			refreshRows(report.selfFortressId, report.enemyFortressId, enemyTargetID);

			selfUnderAttackReportsList_.erase(report.enemyFortressId);
			updateSelfUnderAttackList();

			ui_.textBrowser->append(message + printNewLine());
			break;
		}
	}
}

void FightWidget::refreshRows(id_t rowItemID1, id_t rowItemID2, id_t rowItemID3) {
	refreshOwnedRowById(rowItemID1);
	refreshOwnedRowById(rowItemID2);
	refreshOwnedRowById(rowItemID3);

	refreshEnemyRowById(rowItemID1);
	refreshEnemyRowById(rowItemID2);
	refreshEnemyRowById(rowItemID3);
}

void FightWidget::unsetClickedItemInOwnedTableIfNeccessary(id_t ownedID) {
	FightWidgetRowWidget * rowWidget = ownedFortressesTable_->getClickedRow();

	if (rowWidget != NULL) {				
		if (rowWidget->getItemId() == ownedID) {
			ownedFortressesTable_->setNoRowAsClicked();
		}
	}
}

void FightWidget::unsetClickedItemInEnemyTableIfNeccessary(id_t enemyID) {
	FightWidgetRowWidget * rowWidget = enemyFortressesTable_->getClickedRow();

	if (rowWidget != NULL) {				
		if (rowWidget->getItemId() == enemyID) {
			enemyFortressesTable_->setNoRowAsClicked();
		}
	}
}

void FightWidget::fightProgressReport(const fight_progress_report & report) {
	updateFortressFightData(report.fortressFightData);

	QString hit;
	switch ((AttackResult) report.attackResult) {
		case AR_NOT_FIRED:
		{
			hit += printBlueHeader(L"Žádný výstřel!");
			break;
		}	
		case AR_MISS:
		{
			hit += printBlueHeader(L"Vedle jak ta jedle!");
			break;
		}	
		case AR_FUTILE_HIT:
		{
			hit += printBlueHeader(L"Neškodný zásah!");
			break;
		}	
		case AR_HIT:
		{
			hit += printBlueHeader(L"Zásah!");
			break;
		}	
		case AR_CRITICAL_HIT:
		{
			hit += printBlueHeader(L"Kritický zásah!");
			break;
		}
		case AR_TARGET_ANNIHILATED:
		{
			hit += printBlueHeader(L"Cíl zničen!");
			break;
		}
	}

	QString message;

	if (report.isAttacker) {
		message =
			printGreenHeader(L"Tvoje pevnost vystřelila na nepřítele!")
			+ hit
			+ printNormal(L"Tvoje pevnost")
			+ printStrong(report.attackerFortressName, true)
			+ printNormal(L" zaútočila na nepřátelskou pevnost ")
			+ printStrong(report.defenderFortressName, true)
			+ printNormal(L" hráče ")
			+ printStrong(report.defenderRealmName, true);
	}
	else if (report.isDefender) {
		message =
			printRedHeader(L"Vystřelila na tebe nepřátelská pevnost!")
			+ hit
			+ printNormal(L"Nepřátelská pevnost ")
			+ printStrong(report.attackerFortressName, true)
			+ printNormal(L" hráče ")
			+ printStrong(report.attackerRealmName)
			+ printNormal(L" zaútočila na tvou pevnost ")
			+ printStrong(report.defenderFortressName, true);
	}

	QString attack = 
		printNormal(L"Škody na štítu ") 
		+ printStrongNumber(report.deflectorShieldsEnergyLoss)
		+ printNormal(L" = ")
		+ printStrongPercents(report.deflectorShieldsEnergyLossPerc)
		+ printNewLine()
		+ printNormal(L"Škody na strukturální integritě ") 
		+ printStrongNumber(report.structuralIntegrityLoss)
		+ printNormal(L" = ")
		+ printStrongPercents(report.structuralIntegrityLossPerc);

	if (report.disruptiveBreakdown) {
		attack += 
			printNewLine()
			+ printRedNormal(L"Střela prošla štítem");
	}
	else {
		attack += 
			printNewLine()
			+ printNormal(L"Střela neprošla štítem");
	}

	ui_.textBrowser->append(message + printNewLine() + printNewLine() + attack + printNewLine());

}

void FightWidget::refreshEnemyRowById(id_t rowItemID) {
	FightWidgetRowWidget * enemyRowWidget = enemyFortressesTable_->findRowWidgetById(rowItemID);

	if (enemyRowWidget != NULL) {
		refreshRow(enemyRowWidget);
	}
}

void FightWidget::refreshOwnedRowById(id_t rowItemID) {
	FightWidgetRowWidget * ownedRowWidget = ownedFortressesTable_->findRowWidgetById(rowItemID);

	if (ownedRowWidget != NULL) {
		refreshRow(ownedRowWidget);
	}
}

void FightWidget::refreshRow(FightWidgetRowWidget * rowWidget) {
	id_t rowItemID = rowWidget->getItemId();
	id_t selectedID = getSelectedOwnedFortressID();
	
	bool isAttacking = allAttackingEnemyReports_.find(rowItemID) != allAttackingEnemyReports_.end();
	bool isUnderAttack = allAttackingEnemyReportsByTargetFortress_[rowItemID].size() > 0;

	bool isAttackingOnSelected = allAttackingEnemyReportsByTargetFortress_[selectedID].find(rowItemID) != 
		allAttackingEnemyReportsByTargetFortress_[selectedID].end();

	rowWidget->setAsFight(isAttacking, isAttackingOnSelected, isUnderAttack);
}

void FightWidget::attackStartAcknowledgement(id_t selfFortressId, id_t enemyFortressId) {
	QString message;

	message =
	"<span style=\"color: grey\">"
	+ QString::fromUtf16(L"Server přijal žádost o zahájení útoku")
	+ "</span>";

	ui_.textBrowser->append(message);
}

void FightWidget::attackStopAcknowledgement(id_t selfFortressId) {
	QString message;

	message =
	"<span style=\"color: grey\">"
	+ QString::fromUtf16(L"Server přijal žádost o ukončení útoku")
	+ "</span>";

	ui_.textBrowser->append(message);
}

void FightWidget::attackReportToFightEnemyData(const fight_action_report & report, fight_enemy_data & enemyData) {
	enemyData.fortressId = report.enemyFortressId;
	enemyData.fortressName = report.enemyFortressName;
	enemyData.realmName = report.enemyRealmName;
	enemyData.selfFortressId = report.selfFortressId;
	enemyData.selfFortressName = report.selfFortressName;
	enemyData.isShip = report.enemyIsShip;
}

void FightWidget::attackInformationToFightEnemyData(const fortress_attack_information & data, fight_enemy_data & enemyData) {
	enemyData.fortressId = data.fortressInWeaponsTargetId;
	enemyData.fortressName = data.fortressInWeaponsTargetName;
	enemyData.realmName = data.fortressInWeaponsRangeTargetRealmName;
	enemyData.selfFortressId = data.fortressFightData.id;
	enemyData.selfFortressName = data.fortressFightData.name;
	enemyData.isShip = ((EFortressType) (data.fortressFightData.type)) == FORTRESS_TYPE_SHIP;
}

id_t FightWidget::getSelectedOwnedFortressID() {
	FightWidgetRowWidget * rowWidget = ownedFortressesTable_->getClickedRow();

	if (rowWidget == NULL) {
		return 0;
	}
	
	return rowWidget->getItemId();
}

void FightWidget::setNoPreparedPartner() {
	ui_.submitButton->setEnabled(false);
	ui_.preparedPartner->setNone();	
	ui_.preparedPartnerLabel->setText(QString::fromUtf16(L"Není vybraný nový cíl"));
}

void FightWidget::setNoEnemyPartner() {
	ui_.enemyPartnerLabel->setText(QString::fromUtf16(L"Tvoje pevnost neútočí"));
	ui_.enemyPartner->setNone(L" Tvoje pevnost neútočí");
	ui_.cancelButton->setEnabled(false);
}

void FightWidget::setEnemyPartner(const fight_enemy_data & report) {
	ui_.enemyPartnerLabel->setText(QString::fromUtf16(L"Tvoje pevnost útočí na"));
	ui_.cancelButton->setEnabled(true);				
	ui_.enemyPartner->setPartner(report.fortressId, report.fortressName, report.realmName, false, report.isShip);
}

void FightWidget::setEnemyPartner(const fight_action_report & report) {
	ui_.enemyPartnerLabel->setText(QString::fromUtf16(L"Tvoje pevnost útočí na"));
	ui_.cancelButton->setEnabled(true);				
	ui_.enemyPartner->setPartner(report.enemyFortressId, report.enemyFortressName, report.enemyRealmName, false, report.enemyIsShip);
}

void FightWidget::setNoSelfPartner() {
	ui_.selfPartner->setNone();
}

void FortressFightTable::removeRowAndItemById(id_t itemID) {
	FightWidgetRow * item = findItemById(itemID);

	if (item == NULL) {
		KODIAK_DEBUG_COUT << "Fortress with ID " << itemID << " not found in fortress fight table";
		return;
	}

	int row = findRowOfItem(itemID);

	if (row == -1) {
		KODIAK_DEBUG_COUT << "Fortress with ID " << itemID << " not found in fortress fight table";
		return;
	}

	// If we remove clicked row, than write down that it is no longer selected
	if (clickedFortressRow_ != NULL) {
		if (clickedFortressRow_->getItemId() == itemID) {
			clickedFortressRow_ = NULL;
		}
	}

	removeRowAndItem(item, row);
}

void FightWidget::setGameSecondsPerActualSecond(unsigned long value) {
	NotifyWidget::setGameSecondsPerActualSecond(value);
	ui_.weaponsWidget->setGameSecondsPerActualSecond(value);
}

void FightWidget::notifyUpdate() {
	double difference = getDifferenceFromUpdateTime();

	ui_.shieldsSlider->setValue(getUpdatedValue(fightData_.shieldsEnergy, fightData_.shieldsGradient, difference));
	ui_.integritySlider->setValue(getUpdatedValue(fightData_.actualStructuralIntegrity, fightData_.structuralIntegrityGradient, difference));
	ui_.weaponsWidget->notifyUpdate();
}

void FightWidget::clearState() {
	ownedFortressesTable_->clearAllContent();
	enemyFortressesTable_->clearAllContent();

	ui_.slidersStackedWidget->setCurrentWidget(ui_.infoPage);
	ui_.weaponsWidget->setVisible(false);
}