#include <sstream>
#include <iostream>
#include <string>
#include "commandClient.h"
#include "sharedStructures.h"
#include "threads.h"
#include <exception>
#include "softProj\MainWindow.h"
#include "structs.h"

#include "../gameSettings.h"
#include "../../streams/ErrorStream.h"
extern KODIAK_DEBUG_STREAM KODIAK_DEBUG_COUT;

CommandClient * CommandClientHolder::commandClient_ = 0;

std::string createName(const std::string & devName, const std::string & suffix) {
    std :: stringstream ss;

    ss << devName << suffix;
	return ss.str();
}

CommandClient::CommandClient(ASocketClient * socketClient, MainWindow * mainWindow) {
	this->socketClient_ = socketClient;
	this->mainWindow_ = mainWindow;

	this->messageMapper_ = new HandlerWrapper();

	lastPingAcknowledgementTime_ = clock();

	setPingInterval(5000);
	setTimeLimitForProcessing(500);

	addMessageHandler(REQUEST_CHAT, &CommandClient::processChatMessage);
	addMessageHandler(REQUEST_LOGIN, &CommandClient::processLogin);
	addMessageHandler(REQUEST_SHIPS, &CommandClient::processPlayerShips);
	addMessageHandler(REQUEST_DEVICE_ENERGY_STATE, &CommandClient::processUpdateDeviceEnergyState);
	addMessageHandler(REQUEST_CHANGE_DEVICE_ENERGY_STATE, &CommandClient::processChangeDeviceEnergyState);	
	addMessageHandler(REQUEST_BUDDY, &CommandClient::processBuddies);
	addMessageHandler(REQUEST_BASES, &CommandClient::processPlayerBases);
	addMessageHandler(REQUEST_SHIP_JOURNEY_DETAILS, &CommandClient::processShipJourneyDetails);	
	addMessageHandler(REQUEST_SHIPSINAREA, &CommandClient::processShipsInShipArea);	
	addMessageHandler(REQUEST_SHIP_LOCATION_INFORMATION, &CommandClient::processShipLocationInfo);	
	addMessageHandler(REQUEST_PLANETS, &CommandClient::processPlanetsInStarArea);	

	addMessageHandler(REQUEST_NAVIGATION_STATUS, &CommandClient::processNavigationStatus);	
	addMessageHandler(REQUEST_NAVIGATION_STOP, &CommandClient::processNavigationStop);
	addMessageHandler(REQUEST_NAVIGATION_WARP, &CommandClient::processNavigationWarp);
	addMessageHandler(REQUEST_NAVIGATION_MOVE_TO, &CommandClient::processNavigationMoveTo);
	addMessageHandler(REQUEST_NAVIGATION_ORBIT, &CommandClient::processNavigationOrbit);
	addMessageHandler(REQUEST_NAVIGATION_PURSUIT, &CommandClient::processNavigationPursuit);
	addMessageHandler(REQUEST_NAVIGATION_MOVE_TO_SPOBJ, &CommandClient::processNavigationMoveToSpaceObject);
	addMessageHandler(REQUEST_NAVIGATION_MOVE_TO_SPOBJ_BY_WARP, &CommandClient::processNavigationMoveToSpaceObjectByWarp);
	addMessageHandler(REQUEST_NAVIGATION_BREAK_WARP, &CommandClient::processNavigationBreakWarp);

	addMessageHandler(UPDATE_SHIP, &CommandClient::processUpdateShip);	
	addMessageHandler(REQUEST_SCIENCE, &CommandClient::processUpdateScienceTree);
	addMessageHandler(REQUEST_SHIP_CENTRAL_INFORMATION, &CommandClient::processUpdateFortressCentralInformation);
	addMessageHandler(REQUEST_FORTRESS_SHIELDS_INFORMATION, &CommandClient::processUpdateFortressShieldsInformation);	
	addMessageHandler(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION, &CommandClient::processUpdateShipImpulsDriveInformation);	
	addMessageHandler(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION, &CommandClient::processUpdateShipSubspaceDriveInformation);	
	addMessageHandler(REQUEST_FORTRESS_WEAPONS_INFORMATION, &CommandClient::processUpdateFortressWeaponsInformation);	
	addMessageHandler(REQUEST_FORTRESS_MAINFRAME_INFORMATION, &CommandClient::processUpdateFortressMainframeInformation);
	addMessageHandler(REQUEST_FORTRESS_CREW_INFORMATION, &CommandClient::processUpdateFortressCrewInformation);
	addMessageHandler(REQUEST_FORTRESS_QUARRY_INFORMATION, &CommandClient::processUpdateFortressQuarryInformation);
	addMessageHandler(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION, &CommandClient::processUpdateFortressAccommodationsInformation);
	addMessageHandler(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION, &CommandClient::processUpdateFortressOtherEquipmentInformation);
	addMessageHandler(REQUEST_BASE_FACTORIES_INFORMATION, &CommandClient::processUpdateBaseFactoriesInformation);	
	addMessageHandler(REQUEST_FORTRESS_WAREHOUSES_INFORMATION, &CommandClient::processUpdateFortressWarehousesInformation);	
	addMessageHandler(REQUEST_SHIP_ANDROIDS_INFORMATION, &CommandClient::processUpdateShipAndroidsInformation);	
	addMessageHandler(REQUEST_BASE_ANDROIDS_INFORMATION, &CommandClient::processUpdateBaseAndroidsInformation);	
	addMessageHandler(REQUEST_CHANGE_SHIP_ANDROIDS_STATE, &CommandClient::processChangeShipAndroidsState);	
	addMessageHandler(REQUEST_CHANGE_BASE_ANDROIDS_STATE, &CommandClient::processChangeBaseAndroidsState);	
	addMessageHandler(REQUEST_PING, &CommandClient::processPing);
	addMessageHandler(REQUEST_BASE_HANGAR_ITEM_INFORMATION, &CommandClient::processUpdateBaseHangarItemInformation);	
	addMessageHandler(REQUEST_BASE_HANGARS_INFORMATION, &CommandClient::processUpdateBaseHangarsInformation);	
	addMessageHandler(REQUEST_UNMOUNT_FORTRESS_DEVICE, &CommandClient::processUnmountFortressDevice);	
	addMessageHandler(REQUEST_SEND_TRADE_INVITATION, &CommandClient::processSendTradeInvitation);	
	addMessageHandler(REQUEST_TRADE_PARTNER_FORTRESSES, &CommandClient::processTradePartnerFortresses);	
	addMessageHandler(RECEIVE_TRADE_INVITATION, &CommandClient::processReceiveTradeInvitation);	
	addMessageHandler(REQUEST_DECIDE_TRADE_INVITATION, &CommandClient::processDecideTradeInvitation);	
	addMessageHandler(RECEIVE_TRADE_INVITATION_DECISION, &CommandClient::processReceiveTradeInvitationDecision);		
	addMessageHandler(REQUEST_CANCEL_TRADE, &CommandClient::processCancelTrade);
	addMessageHandler(RECEIVE_TRADE_CANCELATION, &CommandClient::processReceiveTradeCancelation);
	addMessageHandler(REQUEST_DISCOVERED_STARS, &CommandClient::processPlayerDiscoveredStars);
	addMessageHandler(REQUEST_MOVE_TRADE_ITEM, &CommandClient::processMoveTradeItem);
	addMessageHandler(REQUEST_COMMIT_TRADE, &CommandClient::processCommitTrade);
	addMessageHandler(REQUEST_PREPARE_COMMIT_TRADE, &CommandClient::processPrepareCommitTrade);
	addMessageHandler(REQUEST_MOVE_TRADE_RESOURCE, &CommandClient::processMoveTradeResource);
	addMessageHandler(REQUEST_CANCEL_TRADE_COMMIT, &CommandClient::processCancelTradeCommit);	
	addMessageHandler(REQUEST_MOUNT_FORTRESS_DEVICE, &CommandClient::processMountFortressDevice);		
	addMessageHandler(REQUEST_FORTRESSES_IN_WEAPONS_RANGE, &CommandClient::processFortressesInWeaponsRange);		
	addMessageHandler(REQUEST_ATTACK_FORTRESS, &CommandClient::processAttackFortress);		
	addMessageHandler(REQUEST_STOP_ATTACK_FORTRESS, &CommandClient::processStopAttackFortress);		
	addMessageHandler(REQUEST_FIGHT_ACTION_REPORT, &CommandClient::processFightActionReport);	
	addMessageHandler(REQUEST_NAVIGATION_PLANETS, &CommandClient::processNavigationPlanets);
	addMessageHandler(REQUEST_FORTRESSES_IN_CONQUER_RANGE, &CommandClient::processUncontrollableFortresses);
	addMessageHandler(REQUEST_BUILD_NEW_BASE_SHELL, &CommandClient::processBuildNewBaseShell);
	addMessageHandler(REQUEST_AVAILABLE_FORTRESS_CLASSES, &CommandClient::processAvailableFortressClasses);	
	addMessageHandler(REQUEST_FORTRESS_CLASS_DATA, &CommandClient::processFortressClassData);		
	addMessageHandler(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION, &CommandClient::processPlayerFortressesWithBuildInformation);	
	addMessageHandler(REQUEST_CONQUER_FORTRESS, &CommandClient::processConquerFortress);
	addMessageHandler(REQUEST_FORTRESS_ADD_ACCOMMODATIONS, &CommandClient::processFortressAddAccommodations);
	addMessageHandler(REQUEST_FORTRESS_ADD_CREW, &CommandClient::processFortressAddCrew);
	addMessageHandler(REQUEST_FORTRESS_REMOVE_CREW, &CommandClient::processFortressRemoveCrew);
	addMessageHandler(REQUEST_NAVIGATION_DOCK_DOWN, &CommandClient::processNavigationDockDown);	
	addMessageHandler(REQUEST_PLAYER_FORTRESSES, &CommandClient::processPlayerFortresses);	
	addMessageHandler(UPDATE_FORTRESS, &CommandClient::processUpdateFortress);	
	addMessageHandler(REQUEST_REGISTER_PLAYER, &CommandClient::processRegisterPlayer);		
	addMessageHandler(REQUEST_GAME_SECONDS_PER_ACTUAL_SECOND, &CommandClient::processGameSecondsPerActualSecond);		
	addMessageHandler(REQUEST_RENAME_FORTRESS, &CommandClient::processRenameFortress);
	addMessageHandler(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION, &CommandClient::processPlayerFortressesAttackInformation);
	addMessageHandler(REQUEST_HANGAR_BUILD_ITEM, &CommandClient::processHangarBuildItem);	
	addMessageHandler(REQUEST_HANGAR_CANCEL_ITEM, &CommandClient::processHangarCancelItem);
	addMessageHandler(REQUEST_HANGAR_BUILD_SHIP, &CommandClient::processHangarBuildShip);	
	addMessageHandler(REQUEST_FORTRESS_SENSORS_INFORMATION, &CommandClient::processUpdateFortressSensorsInformation);	
	addMessageHandler(REQUEST_FORTRESS_CLOAKING_INFORMATION, &CommandClient::processUpdateFortressCloakingInformation);	
	addMessageHandler(REQUEST_SHIPWARPINFO, &CommandClient::processShipWarpInfo);	
	addMessageHandler(FIGHT_PROGRESS_REPORT, &CommandClient::processFightProgressReport);
	addMessageHandler(REQUEST_NAVIGATION_UNBOUND, &CommandClient::processNavigationUnbound);
}

void CommandClient::setPingInterval(int milliseconds) {
	pingInterval_ = milliseconds;
}

void CommandClient::setTimeLimitForProcessing(int milliseconds) {
	timeLimitForProcessing_ = (milliseconds / (double)1000) * CLOCKS_PER_SEC;
}

void CommandClient::addMessageHandler(const std::string & requestName, TMessageHandler handler) {
	messageMapper_->addHandler(requestName, handler);
}

bool CommandClient::processNextMessage() {
	message * receivedMessage = socketClient_->getNextMessage();
		
	if (receivedMessage) {
		TMessageHandler messageHandler = messageMapper_->findHandler(receivedMessage->getRequestName());

		if (messageHandler != NULL) {
		//	KODIAK_DEBUG_COUT << "HANDLE: Message handler for message " + receivedMessage->getRequestName() + " found!" << KODIAK_ENDL;
			(this->*messageHandler)(receivedMessage);
		}
		else {
			if (receivedMessage->getRequestName() != REQUEST_PING) {
			//	KODIAK_DEBUG_COUT << "HANDLE ERROR: Message handler for message " + receivedMessage->getRequestName() + " not found!" << KODIAK_ENDL;
			}		
		}

		delete receivedMessage;

		return true;
	}

	return false;
}

void CommandClient::pingServer() {
	lastPingAcknowledgementTime_ = clock();
	socketClient_->pingServer();
}
	
void CommandClient::processIncomingMessages() {
	clock_t initTime = clock();
	clock_t elapsedTime = 0;

	if (initTime - lastPingAcknowledgementTime_ >= 2 * pingInterval_) {
		mainWindow_->connectionLostEvent(initTime - lastPingAcknowledgementTime_);			
	}

	if (initTime - lastPingAcknowledgementTime_ >= pingInterval_) { 
		pingServer();			
	}

	while (elapsedTime < timeLimitForProcessing_) {	
		if (!processNextMessage()) {
			return;
		}

		elapsedTime = clock() - initTime;
	}
}

CommandClient::~CommandClient() {
	delete socketClient_;
	delete messageMapper_;
}

bool CommandClient::isActive() {
	return socketClient_->isActive();
}

void CommandClient::login(const LoginDetails & details) {	
	currentLoginInformation_ = details;

	if (isActive()) {
		disconnectFromServer();
		socketClient_->connectToServer(details.server, details.port);
	}
	else {
		socketClient_->connectToServer(details.server, details.port);
	}

	socketClient_->sendAndFreeMessage(requestWriter::login(details.name, details.password));
}

void CommandClient::login(const std::string & username, const std::string & password) {	
	currentLoginInformation_.name = username;
	currentLoginInformation_.password = password;

	socketClient_->sendAndFreeMessage(requestWriter::login(username, password));
}

void CommandClient::sendChatMessage(ChatMessage * chatMessage) {
	socketClient_->sendAndFreeMessage(requestWriter::chat(chatMessage->getBuddyId(), chatMessage->getText()));
}

void CommandClientHolder::setCommandClient(CommandClient * commandClient) {
	commandClient_ = commandClient;
}

CommandClient * CommandClientHolder::getCommandClient() {
	return commandClient_;
}

void CommandClient::processChatMessage(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	id_t buddyId = reader.getId(REQUEST_CHAT_ANSWER_SENDER);
	std::string text = reader.getString(REQUEST_CHAT_ANSWER_MESSAGE);
	std::string timeStamp = reader.getString(REQUEST_CHAT_ANSWER_TIMEFLAG);

	ChatMessage * chatMessage = ChatMessage::createIncomingMessage(buddyId, text, timeStamp);

	mainWindow_->receiveChatMessage(chatMessage);
}

void CommandClient::processLogin(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		std::string reason = reader.getString(REQUEST_LOGIN_ANSWER_FAIL_REASON);
		mainWindow_->answerLoginFAIL(reason);
		return;
	}

	mainWindow_->answerLogin();
}
void CommandClient::playerShips() {
	socketClient_->sendAndFreeMessage(requestWriter::ships());	
}

void CommandClient::shipJourneyDetails(unsigned long shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::ship_journey_details(shipId));
}

void CommandClient::shipsInShipArea(unsigned long shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::shipsinarea(shipId));	
}

void CommandClient::getShipWarpInfo(unsigned long shipId) 
{
	protocolWriter w;
    w.beginMessage(MT_REQUEST, REQUEST_SHIPWARPINFO);
    w.writeValue(REQUEST_SHIPWARPINFO_ANSWER_ID, shipId);
    w.endMessage(true);

	socketClient_->sendAndFreeMessage( w.copyMessage() );
}

void CommandClient::planetsInStarArea(unsigned long areaId) {
	socketClient_->sendAndFreeMessage(requestWriter::planets(areaId));
}

void CommandClient::processPlayerShips(message * protocolMessage) {
	
	ValueReader reader(protocolMessage);

	GameItemsVector items;

	int itemCount = reader.getInt(REQUEST_SHIPS_ANSWER_COUNT);

	for (int i = 1; i < itemCount + 1; ++i) {
		SimpleItem item;

		item.id = reader.getId(REQUEST_SHIPS_ANSWER_SHIPID, i);
		item.name = reader.getString(REQUEST_SHIPS_ANSWER_SHIPNAME, i);
		item.classId = reader.getId(REQUEST_SHIPS_ANSWER_SHIPCLASS, i);

		items.push_back(item);
	}

	mainWindow_->answerShips(items);
}

void CommandClient::playerBases() {
	socketClient_->sendAndFreeMessage(requestWriter::bases());
}

void CommandClient::processPlayerBases(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	GameItemsVector items;

	int itemCount = reader.getInt(REQUEST_BASES_ANSWER_COUNT);

	for (int i = 1; i < itemCount + 1; ++i) {
		SimpleItem item;

		item.id = reader.getId(REQUEST_BASES_ANSWER_BASEID, i);
		item.name = reader.getString(REQUEST_BASES_ANSWER_BASENAME, i);

		// classId is used as type of surface planet
		//item.classId = reader.getId(REQUEST_BASES_ANSWER_BASECLASS, i);
		item.classId = reader.getId(REQUEST_BASES_ANSWER_BASETEXTURE, i);
		
		items.push_back(item);
	}

	mainWindow_->answerBases(items);
}

void CommandClient::changeDeviceEnergyState(unsigned long shipId, requestDeviceEnergy & deviceEnergy) {
	socketClient_->sendAndFreeMessage(requestWriter::change_device_energy_state(shipId, deviceEnergy));
}

void CommandClient::updateDeviceEnergyState(unsigned long shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::device_energy_state(shipId));
}

void CommandClient::processUpdateDeviceEnergyState(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processUpdateDeviceEnergyStateFAIL(reader);
	}
	else {
		id_t shipId = reader.getId(REQUEST_DEVICE_ENERGY_STATE_ANSWER_FORTRESSID);

		answerDeviceEnergy de;

		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_SHIELDS,       de.SHIELDS);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_WEAPONS,       de.WEAPONS);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_TRANSPORT,     de.TRANSPORT);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_HR_SENSORS,    de.HR_SENSORS);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_LR_SENSORS,    de.LR_SENSORS);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_MASKING,       de.MASKING);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_ANDROIDS,      de.ANDROIDS);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_MAINFRAME,     de.MAINFRAME);
		readEnergyState(reader, REQUEST_DEVICE_ENERGY_STATE_ANSWER_LIFE_SUPPORT,  de.LIFE_SUPPORT);

		de.ACC_CURR_ENERGY = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_ACC_CURR_ENERGY);
		de.CURR_ENERGY = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_CURR_ENERGY);
		de.ACC_MAX_ENERGY = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_ACC_MAX_ENERGY);
		de.MAX_ENERGY = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_MAX_ENERGY);

		de.MIN_ENERGY_PRIORITY = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_MIN_ENERGY_PRIORITY);
		de.MAX_ENERGY_PRIORITY = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_MAX_ENERGY_PRIORITY);
		de.MIN_MAX_ENERGY = reader.getDouble(REQUEST_DEVICE_ENERGY_STATE_ANSWER_MIN_MAX_ENERGY);
		de.MIN_RATIO = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_MIN_RATIO);
		de.MAX_RATIO = reader.getULongLong(REQUEST_DEVICE_ENERGY_STATE_ANSWER_MAX_RATIO);

		de.accumulatorGradient = reader.getDouble(REQUEST_DEVICE_ENERGY_STATE_ANSWER_ACCUMULATOR_GRADIENT);
		de.totalEnergyGradient = reader.getDouble(REQUEST_DEVICE_ENERGY_STATE_ANSWER_TOTAL_ENERGY_GRADIENT);

		mainWindow_->answerUpdateDeviceEnergyState(shipId, de);
	}
}

void CommandClient::readEnergyState(const ValueReader & reader, const char* devName, answerDeviceEnergyState & des) {
	stringstream ss;

    ss << devName << REQUEST_DEVICE_ENERGY_STATE_ANSWER_ES_PRIORITY;
    des.priority = reader.getInt(ss.str());
    ss.str(std :: string(""));

    ss << devName << REQUEST_DEVICE_ENERGY_STATE_ANSWER_ES_RATIO;
    des.ratio = reader.getUInt(ss.str());
    ss.str(std :: string(""));

    ss << devName << REQUEST_DEVICE_ENERGY_STATE_ANSWER_ES_MAX_POWER_DRAIN;
	des.maxPowerDrain = reader.getDouble(ss.str());
    ss.str(std :: string(""));

    ss << devName << REQUEST_DEVICE_ENERGY_STATE_ANSWER_ES_SHUT_DOWN_ON_EL;
	des.shutDownOnEnergyLack = reader.getBool(ss.str());
    ss.str(std :: string(""));

    ss << devName << REQUEST_DEVICE_ENERGY_STATE_ANSWER_ES_CONSUMPTION;
    des.consumption = reader.getDouble(ss.str());
	ss.str(std :: string(""));

    ss << devName << REQUEST_DEVICE_ENERGY_STATE_ANSWER_ES_MAX_MAX_POWER_DRAIN;
	des.maxMaxPowerDrain = reader.getDouble(ss.str());
	ss.str(std :: string(""));
}

void CommandClient::buddies() {
	socketClient_->sendAndFreeMessage(requestWriter::buddy());
}

void CommandClient::processBuddies(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	unsigned long buddyCount = reader.getULong(REQUEST_BUDDY_ANSWER_COUNT);

	std::vector<ChatBuddy *> buddies;
    for (int i = 1; i < buddyCount + 1; ++i) {	
        std::stringstream ssID;
        std::stringstream ssNAME;

        ssID << REQUEST_BUDDY_ANSWER_IDPREFIX << i;
		id_t buddyId = reader.getId(ssID.str());

        ssNAME << REQUEST_BUDDY_ANSWER_NAMEPREFIX << i;
		std::string buddyName = reader.getString(ssNAME.str());

		buddies.push_back(new ChatBuddy(buddyId, buddyName));
    }

	mainWindow_->answerBuddies(buddies);
}

void CommandClient::navigationMoveToSpaceObject(id_t shipId, id_t spaceObjectId, unsigned long limit) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_move_to_spobj(shipId, spaceObjectId, limit));	
}

void CommandClient::navigationMoveToSpaceObjectByWarp(id_t shipId, id_t spaceObjectId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_move_to_spobj_by_warp(shipId, spaceObjectId));	
}

void CommandClient::navigationPursuit(id_t shipId, id_t spaceObjectId, unsigned long limit) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_pursuit(shipId, spaceObjectId, limit));
}

void CommandClient::navigationMoveTo(id_t shipId, long long positionx, long long positiony, unsigned long limit) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_move_to(shipId, positionx, positiony, limit));
}

void CommandClient::navigationBreakWarp(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_break_warp(shipId));
}

void CommandClient::navigationOrbit(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_orbit(shipId));
}

void CommandClient::navigationStop(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_stop(shipId));
}

void CommandClient::navigationWarp(id_t shipId, long long positionx, long long positiony) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_warp(shipId, positionx, positiony));
}

void CommandClient::navigationDockDown(id_t shipId, id_t baseId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_dock_down(shipId, baseId));
}

void CommandClient::navigationUnbound(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_unbound(shipId));
}

void CommandClient::processNavigationDockDown(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_DOCK_DOWN_ANSWER_SHIP_ID);
		std::string reason = reader.getString(REQUEST_NAVIGATION_ANSWER_FAIL);
		mainWindow_->answerNavigationDockDownFAIL(shipId, reason);
		return;
	}

	id_t shipId = reader.getId(REQUEST_NAVIGATION_DOCK_DOWN_ANSWER_SHIP_ID);
	id_t baseId = reader.getId(REQUEST_NAVIGATION_DOCK_DOWN_ANSWER_BASE_ID);
	DockingResult result = (DockingResult) reader.getId(REQUEST_NAVIGATION_DOCK_DOWN_ANSWER_DOCKING_RESULT);
    
	mainWindow_->answerNavigationDockDown(shipId, baseId, result);
}

void CommandClient::processNavigationUnbound(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_UNBOUND_ANSWER_SHIP_ID);
		std::string reason = reader.getString(REQUEST_NAVIGATION_ANSWER_FAIL);
		mainWindow_->answerNavigationUnboundFAIL(shipId, reason);
		return;
	}

	id_t shipId = reader.getId(REQUEST_NAVIGATION_UNBOUND_ANSWER_SHIP_ID);
	DockingResult result = (DockingResult) reader.getId(REQUEST_NAVIGATION_UNBOUND_ANSWER_DOCKING_RESULT);
    
	mainWindow_->answerNavigationUnbound(shipId, result);
}

void CommandClient::processShipJourneyDetails(message * protocolMessage) { 
	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processShipJourneyDetailsFAIL(reader);
	}
	else {
		std::string target = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_TARGET);

		if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMT_MOVE_TO_SPACE_OBJECT) {
			processShipJourneyDetailsMOVE_TO_SPACE_OBJECT(reader);
		}
		else if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMT_MOVE_TO_POSITION) {
			processShipJourneyDetailsMOVE_TO(reader);
		}
		else if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMT_MOVE_TO_SHIP) {
			processShipJourneyDetailsPURSUIT(reader);
		}
		else if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMS_REGULAR) {
			processShipJourneyDetailsSTANDARD(reader);
		}
		else if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMT_STOP) {
			processShipJourneyDetailsSTOP(reader);
		}
		else if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMT_ORBIT) {
			processShipJourneyDetailsORBIT(reader);
		}
		else if (target == REQUEST_SHIP_JOURNEY_ANSWER_SMT_NONE) {
			processShipJourneyDetailsNONE(reader);
		}
	}
}

void CommandClient::processShipJourneyDetailsFAIL(const ValueReader & reader) {
	
	ShipJourneyDetailsFAIL details;
		
	details.shipId = reader.getULong(REQUEST_SHIP_JOURNEY_ANSWER_SHIPID);
	details.reason = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_FAIL);	

	mainWindow_->answerShipJourneyDetails(details);
}

void CommandClient::processShipJourneyDetailsNONE(const ValueReader & reader) {
	// It looks like NONE is the same as STANDARD
	processShipJourneyDetailsSTANDARD(reader);
}

void CommandClient::processShipJourneyDetailsORBIT(const ValueReader & reader) {
	// It looks like ORBIT is the same as STANDARD
	processShipJourneyDetailsSTANDARD(reader);
}

void CommandClient::processShipJourneyDetailsSTOP(const ValueReader & reader) { 
	// It looks like STOP is the same as STANDARD
	processShipJourneyDetailsSTANDARD(reader);
}

void CommandClient::processShipJourneyDetailsSTANDARD(const ValueReader & reader) { 

	ShipJourneyDetailsSTANDARD details;

	details.shipId = reader.getId(REQUEST_SHIP_JOURNEY_ANSWER_SHIPID);
	details.positionX = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSX);
	details.positionY = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSY);
	details.target = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_TARGET);
	details.state = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_STATE);
	details.speedInMetersPerSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_SPEED);
	details.accelerationInMetersPerSquaredSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ACCELERATION);
	details.isDockedInBase = reader.getBool(REQUEST_SHIP_JOURNEY_ANSWER_DOCKED_IN_BASE);
	details.docking = (DockingResult) reader.getULong(REQUEST_SHIP_JOURNEY_ANSWER_DOCKING_RESULT);

	mainWindow_->answerShipJourneyDetails(details);
}

void CommandClient::processShipJourneyDetailsPURSUIT(const ValueReader & reader) {

	ShipJourneyDetailsPURSUIT details;

	details.shipId = reader.getId(REQUEST_SHIP_JOURNEY_ANSWER_SHIPID);
	details.positionX = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSX);
	details.positionY = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSY);
	details.target = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_TARGET);
	details.state = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_STATE);
	details.targetShip = reader.getULong(REQUEST_SHIP_JOURNEY_ANSWER_TARGETSHIP);
	details.estimationDistanceInKilometers = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ESTDIST);
	details.estimationTimeInSeconds = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ESTTIME);
	details.speedInMetersPerSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_SPEED);
	details.accelerationInMetersPerSquaredSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ACCELERATION);
	details.docking = (DockingResult) reader.getULong(REQUEST_SHIP_JOURNEY_ANSWER_DOCKING_RESULT);

	mainWindow_->answerShipJourneyDetails(details);
}

void CommandClient::processShipJourneyDetailsMOVE_TO(const ValueReader & reader) {

	ShipJourneyDetailsMOVE_TO details;

	details.shipId = reader.getId(REQUEST_SHIP_JOURNEY_ANSWER_SHIPID);
	details.positionX = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSX);
	details.positionY = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSY);
	details.target = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_TARGET);
	details.state = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_STATE);
	details.estimationDistanceInKilometers = reader.getDistance(REQUEST_SHIP_JOURNEY_ANSWER_ESTDIST);
	details.estimationTimeInSeconds = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ESTTIME);
	details.targetX = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_DPOSX);
	details.targetY = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_DPOSY);
	details.speedInMetersPerSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_SPEED);
	details.accelerationInMetersPerSquaredSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ACCELERATION);
	details.docking = (DockingResult) reader.getULong(REQUEST_SHIP_JOURNEY_ANSWER_DOCKING_RESULT);

	mainWindow_->answerShipJourneyDetails(details);
}

void CommandClient::processShipJourneyDetailsMOVE_TO_SPACE_OBJECT(const ValueReader & reader) {

	ShipJourneyDetailsMOVE_TO_SPACE_OBJECT details;

	details.shipId = reader.getId(REQUEST_SHIP_JOURNEY_ANSWER_SHIPID);
	details.positionX = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSX);
	details.positionY = reader.getPosition(REQUEST_SHIP_JOURNEY_ANSWER_POSY);
	details.target = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_TARGET);
	details.state = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_STATE);
	details.estimationDistanceInKilometers = reader.getDistance(REQUEST_SHIP_JOURNEY_ANSWER_ESTDIST);
	details.estimationTimeInSeconds = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ESTTIME);
	details.targetSpaceObjectName = reader.getString(REQUEST_SHIP_JOURNEY_ANSWER_TARGETNAME);
	details.targetSpaceObjectId = reader.getId(REQUEST_SHIP_JOURNEY_ANSWER_TARGETSPACEOJBECT);
	details.speedInMetersPerSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_SPEED);
	details.accelerationInMetersPerSquaredSecond = reader.getULongLong(REQUEST_SHIP_JOURNEY_ANSWER_ACCELERATION);
	details.docking = (DockingResult) reader.getULong(REQUEST_SHIP_JOURNEY_ANSWER_DOCKING_RESULT);

	mainWindow_->answerShipJourneyDetails(details);
}

void CommandClient::processChangeDeviceEnergyState(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processChangeDeviceEnergyStateFAIL(reader);
	}
}

void CommandClient::processChangeDeviceEnergyStateFAIL(const ValueReader & reader) {

	id_t shipId = reader.getId(REQUEST_CHANGE_DEVICE_ENERGY_STATE_ANSWER_FORTRESSID);
	std::string reason = reader.getString(REQUEST_CHANGE_DEVICE_ENERGY_STATE_ANSWER_FAIL_REASON);

	mainWindow_->answerChangeDeviceEnergyStateERROR(shipId, reason);	
}

void CommandClient::updateRadarData( unsigned long shipId  )
{
	cout<<"NOT IMPLEMENTED: updateRadarData request, shipId: "<<shipId<<endl;
	// TODO
	// send message to client that we want radar data for given ship

}

void CommandClient::processShipsInAreaFAIL(const ValueReader & reader) {
	id_t shipId = reader.getId(REQUEST_SHIPSINAREA_ANSWER_OWNSHIPID);
	std::string fail = reader.getString(REQUEST_SHIPSINAREA_ANSWER_FAIL);

	mainWindow_->answerShipsInShipAreaFAIL(shipId, fail);
}


void CommandClient::processShipWarpInfo(message * protocolMessage)
{
	if (protocolMessage->getAnswerKind() == AK_FAIL) 
	{
		return;
	}

	ValueReader reader(protocolMessage);

	WarpInfo shipWarpInfo;

	shipWarpInfo.shipId = reader.getId( REQUEST_SHIPWARPINFO_ANSWER_ID );
	shipWarpInfo.posX = reader.getPosition( REQUEST_SHIPWARPINFO_ANSWER_POSX );
	shipWarpInfo.posY = reader.getPosition( REQUEST_SHIPWARPINFO_ANSWER_POSY );
	shipWarpInfo.sposX = reader.getPosition( REQUEST_SHIPWARPINFO_ANSWER_SPOSX );
	shipWarpInfo.sposY = reader.getPosition( REQUEST_SHIPWARPINFO_ANSWER_SPOSY );
	shipWarpInfo.dstPosX = reader.getPosition( REQUEST_SHIPWARPINFO_ANSWER_DPOSX );
	shipWarpInfo.dstPosY = reader.getPosition( REQUEST_SHIPWARPINFO_ANSWER_DPOSY );
	shipWarpInfo.stateChange = reader.getBool( REQUEST_SHIPWARPINFO_ANSWER_STATECHANGE );
	shipWarpInfo.inWarp = reader.getBool( REQUEST_SHIPWARPINFO_ANSWER_IN_WARP );
	shipWarpInfo.speed = reader.getDouble( REQUEST_SHIPWARPINFO_ANSWER_SPEED );
	shipWarpInfo.shipName = reader.getString( REQUEST_SHIPWARPINFO_ANSWER_NAME );
	
	unsigned long fortressClassId = reader.getULong( REQUEST_SHIPWARPINFO_ANSWER_TYPE );

	shipWarpInfo.shipType = fortressClassId-1; //-1 because server is indexing from 1, but enums are from 0 on client

	if ( shipWarpInfo.shipType  < 0 || shipWarpInfo.shipType  >= SHIP_TYPE_COUNT )
	{
		KODIAK_WARNING<<"Ship with ID:" + longlongToString( shipWarpInfo.shipId )+ " failed during initialization. fortressClassId for is out of range, required range: <0, " + intToString(SHIP_TYPE_COUNT) + "). FortresClassId was set manualy to 0.";
		shipWarpInfo.shipType = type0;
	}

	this->mainWindow_->answerShipWarpInfo( shipWarpInfo );
}
void CommandClient::processShipsInShipArea(message * protocolMessage) {
	
	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processShipsInAreaFAIL(reader);
	}
	else {
		std::vector< AttackRecord > attackList;

		// PLAYER SHIPS DATA-------------------------------------------------------------------------
		/* steps summary:
			cache data from server first and find active ship
			then set new coord center according to the active ship
			then process all cached ships and store ( with coord center according to the active ship!)
		*/
		vector<PlayerShipDetails> playerShipDetailsContainer;
		unsigned long long shipsOwnCount = reader.getULongLong(REQUEST_SHIPSINAREA_ANSWER_OWN_COUNT);
		for (int counter = 1; counter < shipsOwnCount + 1; ++counter) 
		{
			
			PlayerShipDetails playerShipDetails;
			navigationReadHighResolutionOwnShipDetails(reader, counter, playerShipDetails);

			//cache ship data from server
			playerShipDetailsContainer.push_back( playerShipDetails );

			//find active ship and determine new coord center
			if (  playerShipDetails.shipId == this->mainWindow_->activeShipIdSpaceMap )
			{

				double centerX = GameConstants::MICRO_COORD_CONVERTOR.convertServerToClientValue( playerShipDetails.positionX );
				double centerY = GameConstants::MICRO_COORD_CONVERTOR.convertServerToClientValue( playerShipDetails.positionY );

				//do not change coord center until position change is not greater than centerStepChange
				double centerStepChange = 1000000;
				long long posX = centerX / centerStepChange;
				long long posY = centerY / centerStepChange;

				Point_3<double> pos( posX * centerStepChange , 0, posY * centerStepChange ); 
				GameConstants::MICRO_COORD_CONVERTOR.setClientCoordCenter( pos );
			}
			
		}

		

		//process cached ships with new coord center and store them into SpaceMap data
		for (int i = 0; i < playerShipDetailsContainer.size(); ++i) 
		{
			this->synchronizePlayerShipDetails(playerShipDetailsContainer[i]);
		}

		// SHIPS DATA FROM LONG RANGE RES SENSORS---------------------------------------------------
		unsigned long long shipsLrCount = reader.getULongLong(REQUEST_SHIPSINAREA_ANSWER_LR_COUNT);
		for (int counter = 1; counter < shipsLrCount + 1; ++counter) {
			LongRangeDetails lrDetails;
			this->readLongRangeDetails(reader, counter, lrDetails);
			this->synchronizeShipWithLongRange(lrDetails);
		}

		// SHIPS DATA FROM HIGH RES SENSORS-------------------------------------------------------
		unsigned long long shipsHrCount = reader.getULongLong(REQUEST_SHIPSINAREA_ANSWER_HR_COUNT);
		for (int counter = 1; counter < shipsHrCount + 1; ++counter) {
			HighResolutionDetails hrDetails;
			this->readHighResolutionDetails(reader, counter, hrDetails);
			this->synchronizeShipWithHighResolution(hrDetails);
		}	
			
		this->mainWindow_->shipsInShipAreaDone();
	}
}


void CommandClient::processPlanetsInStarAreaFAIL(const ValueReader & reader) {
	id_t areaId = reader.getId(REQUEST_PLANETS_BAD_ANSWER_BADAREAID);
	std::string fail = reader.getString(REQUEST_PLANETS_BAD_ANSWER_TYPE);
	
	mainWindow_->answerPlanetsInStarAreaFAIL(areaId, fail);
}

void CommandClient::processPlanetsInStarArea(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processPlanetsInStarAreaFAIL(reader);
	}
	else {
		unsigned long planetCount = reader.getULong(REQUEST_PLANETS_ANSWER_COUNT);

		PlanetsInStarAreaDetails planetsInArea;

		planetsInArea.areaId = reader.getId(REQUEST_PLANETS_AREAID);
        planetsInArea.sunObjectRadius = reader.getDouble(REQUEST_PLANETS_ANSWER_SUN_OBJ_RADIUS);
        planetsInArea.sunAreaRadius = reader.getDouble(REQUEST_PLANETS_ANSWER_SUN_ARE_RADIUS);
        planetsInArea.sunName = reader.getString(REQUEST_PLANETS_ANSWER_SUN_NAME);
        planetsInArea.sunWeight = reader.getWeight(REQUEST_PLANETS_ANSWER_SUN_WEIGHT);
        planetsInArea.sunType = reader.getULong(REQUEST_PLANETS_ANSWER_SUN_TYPE);
		planetsInArea.gameTime = reader.getDouble( REQUEST_PLANETS_ANSWER_GAMETIME );
		
		for (int counter = 1; counter < planetCount + 1; ++counter) {
			PlanetDetails planetDetails;
			readPlanetDetails(reader, counter, planetDetails);
			planetsInArea.planets.push_back(planetDetails);
		}

		mainWindow_->answerPlanetsInStarArea(planetsInArea);
	}
}

void CommandClient::readPlanetDetails(const ValueReader & reader, int index, PlanetDetails & details) {	
	details.id = reader.getId(REQUEST_PLANETS_ANSWER_PLANETID, index);
	details.pivotX = reader.getDistance(REQUEST_PLANETS_ANSWER_PIVOTX, index);
	details.pivotY = reader.getDistance(REQUEST_PLANETS_ANSWER_PIVOTY, index);
	details.speed = reader.getSpeed(REQUEST_PLANETS_ANSWER_SPEED, index);
	details.radius = reader.getDistance(REQUEST_PLANETS_ANSWER_RADIUS, index);
	details.size = reader.getDistance(REQUEST_PLANETS_ANSWER_SIZE, index);
	details.angle = reader.getDistance(REQUEST_PLANETS_ANSWER_ANGLE, index);
	details.weight = reader.getWeight(REQUEST_PLANETS_ANSWER_WEIGHT, index);
	details.yearPeriod = reader.getULongLong(REQUEST_PLANETS_ANSWER_YEARP, index);
	details.dayPeriod = reader.getULongLong(REQUEST_PLANETS_ANSWER_DAYP, index);
	details.type = (PlanetType) reader.getULong(REQUEST_PLANETS_ANSWER_TEXTURE, index);
	details.dayTemperature = reader.getLong(REQUEST_PLANETS_ANSWER_DAYTEMP, index);
	details.nightTemperature = reader.getLong(REQUEST_PLANETS_ANSWER_NIGHTTEMP, index);
	details.sea = reader.getLong(REQUEST_PLANETS_ANSWER_SEA, index);
	details.heavyWaterSource = reader.getLong(REQUEST_PLANETS_ANSWER_HEWA, index);
	details.crystalsSource = reader.getLong(REQUEST_PLANETS_ANSWER_ZISO, index);
	details.ilmeniteSource = reader.getLong(REQUEST_PLANETS_ANSWER_ILSO, index);    
	details.name = reader.getString(REQUEST_PLANETS_ANSWER_NAME, index);	

	unsigned long long enemyTargetCount = reader.getULongLong(REQUEST_PLANETS_ANSWER_TARGET_CNT, index);	
	for ( int targetIndex=1; targetIndex < enemyTargetCount +1 ; ++ targetIndex)
	{
		unsigned long enemyTargetId = reader.getULong( create_param_name(REQUEST_PLANETS_ANSWER_TARGET, index, targetIndex) );
		bool targetIsShip = reader.getBool( create_param_name(REQUEST_PLANETS_ANSWER_TARGET_IS_SHIP, index, targetIndex) );

		details.enemyTargetIds.push_back( make_pair(enemyTargetId,targetIsShip)  );
	}

}

void CommandClient::readLongRangeDetails(const ValueReader & reader, int index, LongRangeDetails & details) {
	details.positionX = reader.getPosition(REQUEST_SHIPSINAREA_ANSWER_LR_POSX, index);
	details.positionY = reader.getPosition(REQUEST_SHIPSINAREA_ANSWER_LR_POSY, index);
	details.shipId = reader.getId(REQUEST_SHIPSINAREA_ANSWER_LR_SHIPID, index);
}

void CommandClient::navigationReadLongRangeDetails(const ValueReader & reader, int index, NavigationLongRangeDetails & details) {
	details.positionX = reader.getPosition(REQUEST_NAVIGATION_STATUS_ANSWER_LR_POSX, index);
	details.positionY = reader.getPosition(REQUEST_NAVIGATION_STATUS_ANSWER_LR_POSY, index);
	details.shipId = reader.getId(REQUEST_NAVIGATION_STATUS_ANSWER_LR_SHIPID, index);
	details.distance = reader.getDouble(REQUEST_NAVIGATION_STATUS_ANSWER_LR_DISTANCE, index);
}

void CommandClient::readHighResolutionDetails(const ValueReader & reader, int index, HighResolutionDetails & details)
{
	details.positionX = reader.getPosition(REQUEST_SHIPSINAREA_ANSWER_HR_POSX, index);
	details.positionY = reader.getPosition(REQUEST_SHIPSINAREA_ANSWER_HR_POSY, index);
	details.shipId = reader.getId(REQUEST_SHIPSINAREA_ANSWER_HR_SHIPID, index);
	details.fortressName = reader.getString(REQUEST_SHIPSINAREA_ANSWER_HR_SHIPNAME, index);
	details.currentSpeed = reader.getSpeed(REQUEST_SHIPSINAREA_ANSWER_HR_SPEED, index);
	details.currentAcceleration = reader.getSpeed(REQUEST_SHIPSINAREA_ANSWER_HR_ACCELERATION, index);
	details.courseX = reader.getCourse(REQUEST_SHIPSINAREA_ANSWER_HR_COURSEX, index);
	details.courseY = reader.getCourse(REQUEST_SHIPSINAREA_ANSWER_HR_COURSEY, index);
	details.fortressClassId = reader.getId(REQUEST_SHIPSINAREA_ANSWER_HR_SHIPCLASS, index); //14.7 BUG FIXED: Mantharis
	details.fortressRealm = reader.getString(REQUEST_SHIPSINAREA_ANSWER_HR_PLAYERNAME, index);

	details.enemyTargetId.first = reader.getULong(REQUEST_SHIPSINAREA_ANSWER_HR_TARGET, index);
	details.enemyTargetId.second = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_HR_TARGET_IS_SHIP, index);

	details.inBase = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_HR_INBASE, index);
	details.inWarp = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_HR_INWARP, index);
	details.isOrbiting = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_HR_ORBITING, index);
	
	if (details.isOrbiting)
	{
		details.isMining = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_HR_QUARRYING, index);
		details.orbitingSpeed = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_ORBITING_VELOCITY, index);
		///if ship is on orbit, then hlpPosX,Y says the pivot of the orbit
		details.hlpPosX = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_ORBITING_PIVOT_X, index);
		details.hlpPosY = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_ORBITING_PIVOT_Y, index);
	}

	//TODO, BUG, FIXME: is useless...server is not sendind this message if ship is in warp!!!
	if ( details.inWarp )
	{
		///if ship is in warp, then hlpPosX,Y says where is the ship now ( positionX, positionY is invalid at this moment)
		details.hlpPosX = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_WARP_PIVOT_X, index);
		details.hlpPosY = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_WARP_PIVOT_Y, index);
	}
	if ( details.inBase )
	{
		///if ship is in base, then hlpPosX,Y says the position of the planet, where is the ship  ( positionX, positionY is invalid at this moment)
		details.hlpPosX = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_BASE_PIVOT_X, index);
		details.hlpPosY = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_HR_BASE_PIVOT_Y, index);
	}


	
	

}

void CommandClient::navigationReadHighResolutionOwnShipDetails(const ValueReader & reader, int index, PlayerShipDetails & details)
{
	details.positionX = reader.getPosition(REQUEST_SHIPSINAREA_ANSWER_OWN_POSX, index);
	details.positionY = reader.getPosition(REQUEST_SHIPSINAREA_ANSWER_OWN_POSY, index);
	details.shipId = reader.getId(REQUEST_SHIPSINAREA_ANSWER_OWN_SHIPID, index);
	details.fortressName = reader.getString(REQUEST_SHIPSINAREA_ANSWER_OWN_SHIPNAME, index);
	details.currentSpeed = reader.getSpeed(REQUEST_SHIPSINAREA_ANSWER_OWN_SPEED, index);
	details.currentAcceleration = reader.getSpeed(REQUEST_SHIPSINAREA_ANSWER_OWN_ACCELERATION, index);
	details.courseX = reader.getCourse(REQUEST_SHIPSINAREA_ANSWER_OWN_COURSEX, index);
	details.courseY = reader.getCourse(REQUEST_SHIPSINAREA_ANSWER_OWN_COURSEY, index);
	details.fortressClassId = reader.getId(REQUEST_SHIPSINAREA_ANSWER_OWN_SHIPCLASS, index);
	details.fortressRealm = reader.getString(REQUEST_SHIPSINAREA_ANSWER_OWN_PLAYERNAME, index);
	details.targetDistance = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_ESTIMATION_DISTANCE, index);
	details.shieldStatus = reader.getInt(REQUEST_SHIPSINAREA_ANSWER_OWN_SHIELD_PERC, index);
	details.lifeStatus = reader.getInt(REQUEST_SHIPSINAREA_ANSWER_OWN_STRUCT_INT_PERC, index);

	details.enemyTargetId.first = reader.getULong(REQUEST_SHIPSINAREA_ANSWER_OWN_TARGET, index);
	details.enemyTargetId.second = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_OWN_TARGET_IS_SHIP, index);

	details.inBase = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_OWN_INBASE, index);
	details.inWarp = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_OWN_INWARP, index);
	details.isOrbiting = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_OWN_ORBITING, index);

	if (details.isOrbiting)
	{
		details.isMining = reader.getBool(REQUEST_SHIPSINAREA_ANSWER_OWN_QUARRYING, index);
		details.orbitingSpeed = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_ORBITING_VELOCITY, index);
		///if ship is on orbit, then hlpPosX,Y says the pivot of the orbit
		details.hlpPosX = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_ORBITING_PIVOT_X, index);
		details.hlpPosY = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_ORBITING_PIVOT_Y, index);
	}
	if ( details.inWarp )
	{
		///if ship is in warp, then hlpPosX,Y says where is the ship now ( positionX, positionY is invalid at this moment)
		details.hlpPosX = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_WARP_PIVOT_X, index);
		details.hlpPosY = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_WARP_PIVOT_Y, index);
	}
	if ( details.inBase )
	{
		///if ship is in base, then hlpPosX,Y says the position of the planet, where is the ship  ( positionX, positionY is invalid at this moment)
		details.hlpPosX = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_BASE_PIVOT_X, index);
		details.hlpPosY = reader.getDouble(REQUEST_SHIPSINAREA_ANSWER_OWN_BASE_PIVOT_Y, index);
	}

}

void CommandClient::navigationReadHighResolutionDetails(const ValueReader & reader, int index, NavigationHighResolutionDetails & details)
{
	details.positionX = reader.getPosition(REQUEST_NAVIGATION_STATUS_ANSWER_HR_POSX, index);
   	details.positionY = reader.getPosition(REQUEST_NAVIGATION_STATUS_ANSWER_HR_POSY, index);
	details.shipId = reader.getId(REQUEST_NAVIGATION_STATUS_ANSWER_HR_SHIPID, index);
 	details.fortressName = reader.getString(REQUEST_NAVIGATION_STATUS_ANSWER_HR_SHIPNAME, index);
	details.currentSpeed = reader.getSpeed(REQUEST_NAVIGATION_STATUS_ANSWER_HR_SPEED, index);
	details.currentAcceleration = reader.getSpeed(REQUEST_NAVIGATION_STATUS_ANSWER_HR_ACCELERATION, index);
	details.courseX = reader.getCourse(REQUEST_NAVIGATION_STATUS_ANSWER_HR_COURSEX, index);
 	details.courseY = reader.getCourse(REQUEST_NAVIGATION_STATUS_ANSWER_HR_COURSEY, index);
	details.fortressRealm = reader.getString(REQUEST_SHIPSINAREA_ANSWER_HR_PLAYERNAME, index);
	details.distance = reader.getDouble(REQUEST_NAVIGATION_STATUS_ANSWER_HR_DISTANCE, index);
}

void CommandClient::synchronizeShipWithLongRange( LongRangeDetails &lrDetails )
{
	ShipDataBasic shipData;
	shipData.id = lrDetails.shipId;
	shipData.position.set_data( lrDetails.positionX, 0, lrDetails.positionY);

	// below ship informations are not known
	shipData.dstPosition = shipData.position;
	shipData.acceleration = 0;
	shipData.speed = 0;
	shipData.name = "";

	// long range sensors give us only temporary ships positions
	// so we change alpha of the ships to visualise fact that
	// the ship position may not be actual
	mainWindow_->synchronizer_->shipSynchronizeMacro(shipData, true);

}

void setShipDataFromHighResolutionDetails( HighResolutionDetails & details, ShipDataDetails & dstShipData  )
{
	dstShipData.id = details.shipId;
	dstShipData.type = (ShipType) (details.fortressClassId-1); //-1 because server is indexing from 1, but enums are from 0 on client

	if ( dstShipData.type < 0 || dstShipData.type >= SHIP_TYPE_COUNT )
	{
		KODIAK_WARNING<<"Ship with ID:" + longlongToString( dstShipData.id )+ " failed during initialization. fortressClassId for is out of range, required range: <0, " + intToString(SHIP_TYPE_COUNT) + "). FortresClassId was set manualy to 0.";
		dstShipData.type = type0;
	}

	dstShipData.position.set_data(details.positionX, 0, details.positionY);

	Vector_3<double> course;
	course.set_data( details.courseX, 0, details.courseY);

	// normalize if not zero lenght vector
	if ( course != Vector_3<double>(0,0,0) )
	{
		course.normalize();
	}

	Point_3<double> destinationPosition;
	destinationPosition.set_data(details.positionX, 0, details.positionY);
	destinationPosition += course * details.targetDistance;

	dstShipData.dstPosition = destinationPosition;
	dstShipData.name = details.fortressName;
	dstShipData.speed = details.currentSpeed;
	dstShipData.acceleration = details.currentAcceleration;

	dstShipData.isOrbiting = details.isOrbiting;
	dstShipData.isMining = details.isMining;
	dstShipData.orbitSpeed = details.orbitingSpeed;

	dstShipData.enemyTarget.enemyTargetId = details.enemyTargetId.first;

	if (  details.enemyTargetId.first == false )
	{
		dstShipData.enemyTarget.targetType = NO_TARGET; 
	}
	else if (  details.enemyTargetId.second )
	{
		dstShipData.enemyTarget.targetType = SHIP_TARGET; 
	}
	else
	{
		dstShipData.enemyTarget.targetType = PLANET_TARGET; 
	}

	dstShipData.inBase = details.inBase;
	dstShipData.inWarp = details.inWarp;

	//Not kown atributes
	dstShipData.lifePercentage = 100;
	dstShipData.shieldPercentage = 100;

	if ( details.isOrbiting )
	{
		dstShipData.orbitPivot.set_data( details.hlpPosX, 0, details.hlpPosY );
	}

	//if ship is in base or in warp then details.position from server is invalid for some reason 
	//but hlpPosX,Y stores in such case ship position
	if ( details.inBase || details.inWarp )
	{
		dstShipData.position.set_data( details.hlpPosX, 0, details.hlpPosY );
	}

	
}

void setShipDataFromPlayerShipDetails( PlayerShipDetails & details, ShipDataDetails & dstShipData  )
{
	setShipDataFromHighResolutionDetails( details, dstShipData );
	
	dstShipData.lifePercentage = details.lifeStatus;
	dstShipData.shieldPercentage = details.shieldStatus;
}

void CommandClient::synchronizeShipWithHighResolution(HighResolutionDetails & details) {
	ShipDataDetails shipData;
   
	setShipDataFromHighResolutionDetails( details, shipData );

	//this synchronization methos is used for SpaceMapView mode
	mainWindow_->synchronizer_->shipSynchronize(shipData);
}

void CommandClient::synchronizePlayerShipDetails( PlayerShipDetails & details) {
	ShipDataDetails shipData;
   
	setShipDataFromPlayerShipDetails( details, shipData );

	//this synchronization methos is used for SpaceMapView mode
	mainWindow_->synchronizer_->shipSynchronize(shipData);
}

void CommandClient::navigationStatus(unsigned long shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_status(shipId));
}

void CommandClient::processNavigationStatus(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	NavigationStatus navigationStatus;

	unsigned long myShipsCount = reader.getULong(REQUEST_NAVIGATION_STATUS_ANSWER_MYSHIPCOUNT);

	for (int i = 1; i < myShipsCount + 1; ++i) {
		NavigationObject navigation;
		navigationReadShip(reader, i, navigation);
		navigationStatus.myShips.push_back(navigation);
	}

	unsigned long myBasesCount = reader.getULong(REQUEST_NAVIGATION_STATUS_ANSWER_MYBASECOUNT);

	for (int i = 1; i < myBasesCount + 1; ++i) {
		NavigationBaseObject navigation;
		navigationReadBase(reader, i, navigation);
		navigationStatus.myBases.push_back(navigation);
	}

	unsigned long shipsInLongRangeCount = reader.getULong(REQUEST_SHIPSINAREA_ANSWER_LR_COUNT);

	for (int i = 1; i < shipsInLongRangeCount + 1; ++i) {
		NavigationLongRangeDetails navigation;
		navigationReadLongRangeDetails(reader, i, navigation);
		navigationStatus.shipsInLongRange.push_back(navigation);
	}

	unsigned long shipsInHighResolutionCount = reader.getULong(REQUEST_SHIPSINAREA_ANSWER_HR_COUNT);

	for (int i = 1; i < shipsInHighResolutionCount + 1; ++i) {
		NavigationHighResolutionDetails navigation;
		navigationReadHighResolutionDetails(reader, i, navigation);
		navigationStatus.shipsInHighResolution.push_back(navigation);
	}

	unsigned long discoveredStarCount = reader.getULong(REQUEST_NAVIGATION_STATUS_ANSWER_DISCOVERED_STAR_COUNT);

	for (int i = 1; i < discoveredStarCount + 1; ++i) {
		NavigationObject navigation;
		navigationReadStar(reader, i, navigation);
		navigationStatus.discoveredStars.push_back(navigation);
	}	

	mainWindow_->answerUpdateNavigationStatus(navigationStatus);	
}

void CommandClient::navigationReadShip(const ValueReader & reader, int index, NavigationObject & navigation)
{
	navigation.id = reader.getId(REQUEST_NAVIGATION_STATUS_ANSWER_MYSHIPID, index);
	navigation.name = reader.getString(REQUEST_NAVIGATION_STATUS_ANSWER_MYSHIPNAME, index);
	navigation.distance = reader.getDouble(REQUEST_NAVIGATION_STATUS_ANSWER_MYSHIPDISTANCE, index);
}

void CommandClient::navigationReadBase(const ValueReader & reader, int index, NavigationBaseObject & navigation)
{
	navigation.id = reader.getId(REQUEST_NAVIGATION_STATUS_ANSWER_MYBASEID, index);
	navigation.name = reader.getString(REQUEST_NAVIGATION_STATUS_ANSWER_MYBASENAME, index);
	navigation.distance = reader.getDouble(REQUEST_NAVIGATION_STATUS_ANSWER_MYBASEDISTANCE, index);
	navigation.canShipDockDown = (DockingResult) reader.getULong(REQUEST_NAVIGATION_STATUS_ANSWER_CAN_SHIP_DOCK_DOWN, index);
}

void CommandClient::navigationReadStar(const ValueReader & reader, int index, NavigationObject & navigation)
{
    navigation.id = reader.getId(REQUEST_NAVIGATION_STATUS_ANSWER_DISCOVERED_STAR_ID, index);
	navigation.distance = reader.getDouble(REQUEST_NAVIGATION_STATUS_ANSWER_DISCOVERED_STAR_DISTANCE, index);
	navigation.name = reader.getString(REQUEST_NAVIGATION_STATUS_ANSWER_DISCOVERED_STAR_NAME, index);
}

void CommandClient::processNavigationShipFAIL(const ValueReader & reader) {
	id_t shipId = reader.getId(REQUEST_NAVIGATION_ANSWER_SHIPID);
	std::string fail = reader.getString(REQUEST_NAVIGATION_ANSWER_FAIL);

	mainWindow_->answerNavigationShipFAIL(shipId, fail);
}

void CommandClient::processNavigationMoveToSpaceObject(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationMoveToSpaceObjectFAIL();
	}
	else {
		ValueReader reader(protocolMessage);

		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationMoveToSpaceObject(shipId);
	}
}

void CommandClient::processNavigationMoveToSpaceObjectByWarp(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationMoveToSpaceObjectByWarpFAIL();
	}
	else {				
		mainWindow_->answerNavigationMoveToSpaceObjectByWarp(shipId);
	}
}

void CommandClient::processNavigationMoveTo(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationMoveToFAIL();
	}
	else {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationMoveTo(shipId);
	}
}

void CommandClient::processNavigationPursuit(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationPursuitFAIL();
	}
	else {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationPursuit(shipId);
	}
}

void CommandClient::processNavigationBreakWarp(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationBreakWarpFAIL();
	}
	else {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationBreakWarp(shipId);
	}
}

void CommandClient::processNavigationOrbit(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationOrbitFAIL();
	}
	else {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationOrbit(shipId);
	}
}

void CommandClient::processNavigationStop(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationStopFAIL();
	}
	else {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationStop(shipId);
	}
}

void CommandClient::processNavigationWarp(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		mainWindow_->answerNavigationWarpFAIL();
	}
	else {
		id_t shipId = reader.getId(REQUEST_NAVIGATION_SHIPID);
		mainWindow_->answerNavigationWarp(shipId);
	}
}

void CommandClient::navigationPlanetsInStarArea(id_t areaId) {
	socketClient_->sendAndFreeMessage(requestWriter::planets(areaId));
}

void CommandClient::navigationPlanetsInStarArea(id_t shipId, id_t areaId) {
	socketClient_->sendAndFreeMessage(requestWriter::navigation_planets(shipId, areaId));
}

void CommandClient::updateScienceTree() {
	socketClient_->sendAndFreeMessage(requestWriter::science());
}

void CommandClient::changeScienceTree(sciencetree_raw_data & data) {
	socketClient_->sendAndFreeMessage(requestWriter::change_science(data));
}

void CommandClient::processUpdateScienceTree(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	ScienceTreeRawUpdateData data;

	data.tokensSCIENCE_ENTITY_SHIPS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_SHIPS);
	data.tokensSCIENCE_ENTITY_BASES = reader.getULongLong(TOKENS_SCIENCE_ENTITY_SHIPS);
	data.tokensSCIENCE_ENTITY_ENERGETIC_ACCUMULATOR = reader.getULongLong(TOKENS_SCIENCE_ENTITY_ENERGETIC_ACCUMULATOR);
	data.tokensSCIENCE_ENTITY_NAVIGATION_COMPUTER = reader.getULongLong(TOKENS_SCIENCE_ENTITY_NAVIGATION_COMPUTER);
	data.tokensSCIENCE_ENTITY_QUARK_GLUON_CORE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_QUARK_GLUON_CORE);
	data.tokensSCIENCE_ENTITY_SUBSPACE_BEACON = reader.getULongLong(TOKENS_SCIENCE_ENTITY_SUBSPACE_BEACON);
	data.tokensSCIENCE_ENTITY_INERTIAL_DAMPERS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_INERTIAL_DAMPERS);
	data.tokensSCIENCE_ENTITY_IMPULS_JET_ENGINE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_IMPULS_JET_ENGINE);
	data.tokensSCIENCE_ENTITY_MECHANICAL_DAMPERS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_MECHANICAL_DAMPERS);
	data.tokensSCIENCE_ENTITY_DEFLECTOR_SHIELDS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_DEFLECTOR_SHIELDS);
	data.tokensSCIENCE_ENTITY_WEAPON_ENERGY_CIRCUIT = reader.getULongLong(TOKENS_SCIENCE_ENTITY_WEAPON_ENERGY_CIRCUIT);
	data.tokensSCIENCE_ENTITY_DRONE_MISSILE_LAUNCHER = reader.getULongLong(TOKENS_SCIENCE_ENTITY_DRONE_MISSILE_LAUNCHER);
	data.tokensSCIENCE_ENTITY_DRONE_MISSILES = reader.getULongLong(TOKENS_SCIENCE_ENTITY_DRONE_MISSILES);
	data.tokensSCIENCE_ENTITY_LASER_GUN = reader.getULongLong(TOKENS_SCIENCE_ENTITY_LASER_GUN);	
	data.tokensSCIENCE_ENTITY_TRANSPORT_BEAM_GENERATOR = reader.getULongLong(TOKENS_SCIENCE_ENTITY_TRANSPORT_BEAM_GENERATOR);
	data.tokensSCIENCE_ENTITY_MAGNETICAL_COLLECTORS_OF_PLASMA = reader.getULongLong(TOKENS_SCIENCE_ENTITY_MAGNETICAL_COLLECTORS_OF_PLASMA);
	data.tokensSCIENCE_ENTITY_SUBMERSIBLE_FILTRATION_TANK = reader.getULongLong(TOKENS_SCIENCE_ENTITY_SUBMERSIBLE_FILTRATION_TANK);
	data.tokensSCIENCE_ENTITY_SUBMARINE_MINING_MACHINE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_SUBMARINE_MINING_MACHINE);
	data.tokensSCIENCE_ENTITY_UNDERGROUND_DRILLING_MACHINE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_UNDERGROUND_DRILLING_MACHINE);
	data.tokensSCIENCE_ENTITY_PROBE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_PROBE);
	data.tokensSCIENCE_ENTITY_HIGH_RESOLUTION_SENSORS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_HIGH_RESOLUTION_SENSORS);
	data.tokensSCIENCE_ENTITY_LONG_RANGE_SENSORS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_LONG_RANGE_SENSORS);
	data.tokensSCIENCE_ENTITY_CLOAKING_DEVICE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_CLOAKING_DEVICE);
	data.tokensSCIENCE_ENTITY_ANDROIDS = reader.getULongLong(TOKENS_SCIENCE_ENTITY_ANDROIDS);
	data.tokensSCIENCE_ENTITY_SCIENTIFIC_LAB = reader.getULongLong(TOKENS_SCIENCE_ENTITY_SCIENTIFIC_LAB);
	data.tokensSCIENCE_ENTITY_MAINFRAME = reader.getULongLong(TOKENS_SCIENCE_ENTITY_MAINFRAME);
	data.tokensSCIENCE_ENTITY_HANGAR = reader.getULongLong(TOKENS_SCIENCE_ENTITY_HANGAR);
	data.tokensSCIENCE_ENTITY_MAGNETICAL_FILTER = reader.getULongLong(TOKENS_SCIENCE_ENTITY_MAGNETICAL_FILTER);
	data.tokensSCIENCE_ENTITY_DEUTERIUM_DECOMPOSER = reader.getULongLong(TOKENS_SCIENCE_ENTITY_DEUTERIUM_DECOMPOSER);
	data.tokensSCIENCE_ENTITY_ZIRCONIUM_REACTOR = reader.getULongLong(TOKENS_SCIENCE_ENTITY_ZIRCONIUM_REACTOR);
	data.tokensSCIENCE_ENTITY_ILMENITE_FURNACE = reader.getULongLong(TOKENS_SCIENCE_ENTITY_ILMENITE_FURNACE);
	data.tokensSCIENCE_ENTITY_LIFE_SUPPORT = reader.getULongLong(TOKENS_SCIENCE_ENTITY_LIFE_SUPPORT);

	data.tokensSCIENCE_SUPREME_ENTITY_SCIENCE = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_SCIENCE);

	data.tokensSCIENCE_SUPREME_ENTITY_DRIVE = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_DRIVE);
	data.tokensSCIENCE_SUPREME_ENTITY_PLATFORM = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_PLATFORM);
	data.tokensSCIENCE_SUPREME_ENTITY_MODULES = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_MODULES);
	data.tokensSCIENCE_SUPREME_ENTITY_PRODUCTION = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_PRODUCTION);

	data.tokensSCIENCE_SUPREME_ENTITY_SUBSPACE_DRIVE = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_SUBSPACE_DRIVE);
	data.tokensSCIENCE_SUPREME_ENTITY_IMPULS_DRIVE = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_IMPULS_DRIVE);
	data.tokensSCIENCE_SUPREME_ENTITY_CONSTRUCTION = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_CONSTRUCTION);
	data.tokensSCIENCE_SUPREME_ENTITY_EQUIPMENT = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_EQUIPMENT);
	data.tokensSCIENCE_SUPREME_ENTITY_ENERGETIC_RING = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_ENERGETIC_RING);
	data.tokensSCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES);
	data.tokensSCIENCE_SUPREME_ENTITY_FACTORIES = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_FACTORIES);
	data.tokensSCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES);
	data.tokensSCIENCE_SUPREME_ENTITY_QUARRYING_MACHINES = reader.getULongLong(TOKENS_SCIENCE_SUPREME_ENTITY_QUARRYING_MACHINES);

	/** Special points (percents) */
	
	data.specPtsQUARK_GLUON_CORE_SPEED = reader.getULongLong(SPEC_PTS_QUARK_GLUON_CORE_SPEED);
	data.specPtsQUARK_GLUON_CORE_CONSUMPTION = reader.getULongLong(SPEC_PTS_QUARK_GLUON_CORE_CONSUMPTION);

	data.specPtsNAVIGATION_COMPUTER_SPEED = reader.getULongLong(SPEC_PTS_NAVIGATION_COMPUTER_SPEED);

	data.specPtsSUBSPACE_BEACON_SPEED = reader.getULongLong(SPEC_PTS_SUBSPACE_BEACON_SPEED);

	data.specPtsINERTIAL_DAMPERS_SPEED = reader.getULongLong(SPEC_PTS_INERTIAL_DAMPERS_SPEED);

	data.specPtsIMPULS_ENGINE_FORCE = reader.getULongLong(SPEC_PTS_IMPULS_ENGINE_FORCE);
	data.specPtsIMPULS_ENGINE_CONSUMPTION = reader.getULongLong(SPEC_PTS_IMPULS_ENGINE_CONSUMPTION);

	data.specPtsMECHANICAL_DAMPERS_ACCELERATION = reader.getULongLong(SPEC_PTS_MECHANICAL_DAMPERS_ACCELERATION);

	data.specPtsDRONE_MISSILES_DAMAGE = reader.getULongLong(SPEC_PTS_DRONE_MISSILES_DAMAGE);
	data.specPtsDRONE_MISSILES_PRECISION = reader.getULongLong(SPEC_PTS_DRONE_MISSILES_PRECISION);
	data.specPtsDRONE_MISSILES_RANGE = reader.getULongLong(SPEC_PTS_DRONE_MISSILES_RANGE);

	data.specPtsDRONE_MISSILE_LAUNCHER_ACCUMULATOR = reader.getULongLong(SPEC_PTS_DRONE_MISSILE_LAUNCHER_ACCUMULATOR);
	data.specPtsDRONE_MISSILE_LAUNCHER_CHARGING = reader.getULongLong(SPEC_PTS_DRONE_MISSILE_LAUNCHER_CHARGING);

	data.specPtsSHIPS_LEVEL = reader.getULongLong(SPEC_PTS_SHIPS_LEVEL);

	data.specPtsBASES_LEVEL = reader.getULongLong(SPEC_PTS_BASES_LEVEL);

	data.specPtsHANGARS_LEVEL = reader.getULongLong(SPEC_PTS_HANGARS_LEVEL);

	data.specPtsANDROIDS_LEVEL = reader.getULongLong(SPEC_PTS_ANDROIDS_LEVEL);
	data.specPtsANDROIDS_CONSUMPTION = reader.getULongLong(SPEC_PTS_ANDROIDS_CONSUMPTION);

	data.specPtsENERGETIC_ACCUMULATOR_ACCUMULATOR = reader.getULongLong(SPEC_PTS_ENERGETIC_ACCUMULATOR_ACCUMULATOR);
	data.specPtsENERGETIC_ACCUMULATOR_CHARGING = reader.getULongLong(SPEC_PTS_ENERGETIC_ACCUMULATOR_CHARGING);

	data.specPtsMAINFRAME_BIO_NODES = reader.getULongLong(SPEC_PTS_MAINFRAME_BIO_NODES);
	data.specPtsMAINFRAME_PREDICTION = reader.getULongLong(SPEC_PTS_MAINFRAME_PREDICTION);
	data.specPtsMAINFRAME_TIME_REUSABILITY = reader.getULongLong(SPEC_PTS_MAINFRAME_TIME_REUSABILITY);
	data.specPtsMAINFRAME_CONSUMPTION = reader.getULongLong(SPEC_PTS_MAINFRAME_CONSUMPTION);

	data.specPtsSCIENTIFIC_LABS_LEVEL = reader.getULongLong(SPEC_PTS_SCIENTIFIC_LABS_LEVEL);

	data.specPtsLIFE_SUPPORT_CAPACITY = reader.getULongLong(SPEC_PTS_LIFE_SUPPORT_CAPACITY);
	data.specPtsLIFE_SUPPORT_CONSUMPTION = reader.getULongLong(SPEC_PTS_LIFE_SUPPORT_CONSUMPTION);

	data.specPtsWEAPON_ENERGY_CIRCUIT_CHARGING = reader.getULongLong(SPEC_PTS_WEAPON_ENERGY_CIRCUIT_CHARGING);

	data.specPtsTRANSPORT_BEAM_GENERATOR_ACCUMULATOR = reader.getULongLong(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_ACCUMULATOR);
	data.specPtsTRANSPORT_BEAM_GENERATOR_CHARGING = reader.getULongLong(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_CHARGING);
	data.specPtsTRANSPORT_BEAM_GENERATOR_FORCIBILITY = reader.getULongLong(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_FORCIBILITY);
	data.specPtsTRANSPORT_BEAM_GENERATOR_PRECISION = reader.getULongLong(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_PRECISION);
	data.specPtsTRANSPORT_BEAM_GENERATOR_RANGE = reader.getULongLong(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_RANGE);

	data.specPtsLASER_GUN_ACCUMULATOR = reader.getULongLong(SPEC_PTS_LASER_GUN_ACCUMULATOR);
	data.specPtsLASER_GUN_CHARGING = reader.getULongLong(SPEC_PTS_LASER_GUN_CHARGING);
	data.specPtsLASER_GUN_FORCIBILITY = reader.getULongLong(SPEC_PTS_LASER_GUN_FORCIBILITY);
	data.specPtsLASER_GUN_PRECISION = reader.getULongLong(SPEC_PTS_LASER_GUN_PRECISION);
	data.specPtsLASER_GUN_RANGE = reader.getULongLong(SPEC_PTS_LASER_GUN_RANGE);

	data.specPtsDEFLECTOR_SHIELDS_GENERATOR_SOLIDITY = reader.getULongLong(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_SOLIDITY);
	data.specPtsDEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR = reader.getULongLong(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR);
	data.specPtsDEFLECTOR_SHIELDS_GENERATOR_CHARGING = reader.getULongLong(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_CHARGING);

	data.specPtsHIGH_RESOLUTION_SENSORS_LEVEL = reader.getULongLong(SPEC_PTS_HIGH_RESOLUTION_SENSORS_LEVEL);
	data.specPtsHIGH_RESOLUTION_SENSORS_RANGE = reader.getULongLong(SPEC_PTS_HIGH_RESOLUTION_SENSORS_RANGE);
	data.specPtsHIGH_RESOLUTION_SENSORS_CONSUMPTION = reader.getULongLong(SPEC_PTS_HIGH_RESOLUTION_SENSORS_CONSUMPTION);

	data.specPtsLONG_RANGE_SENSORS_LEVEL = reader.getULongLong(SPEC_PTS_LONG_RANGE_SENSORS_LEVEL);
	data.specPtsLONG_RANGE_SENSORS_RANGE = reader.getULongLong(SPEC_PTS_LONG_RANGE_SENSORS_RANGE);
	data.specPtsLONG_RANGE_SENSORS_CONSUMPTION = reader.getULongLong(SPEC_PTS_LONG_RANGE_SENSORS_CONSUMPTION);

	data.specPtsCLOAKING_DEVICE_LEVEL = reader.getULongLong(SPEC_PTS_CLOAKING_DEVICE_LEVEL);
	data.specPtsCLOAKING_DEVICE_CONSUMPTION = reader.getULongLong(SPEC_PTS_CLOAKING_DEVICE_CONSUMPTION);

	data.specPtsPROBE_DEVICE_LEVEL = reader.getULongLong(SPEC_PTS_PROBE_DEVICE_LEVEL);

	data.specPtsMAGNETICAL_FILTER_PRODUCTION = reader.getULongLong(SPEC_PTS_MAGNETICAL_FILTER_PRODUCTION);

	data.specPtsDEUTERIUM_DECOMPOSER_PRODUCTION = reader.getULongLong(SPEC_PTS_DEUTERIUM_DECOMPOSER_PRODUCTION);
	data.specPtsDEUTERIUM_DECOMPOSER_METAMORPHOSIS = reader.getULongLong(SPEC_PTS_DEUTERIUM_DECOMPOSER_METAMORPHOSIS);

	data.specPtsZIRCONIUM_REACTOR_PRODUCTION = reader.getULongLong(SPEC_PTS_ZIRCONIUM_REACTOR_PRODUCTION);
	data.specPtsZIRCONIUM_REACTOR_METAMORPHOSIS = reader.getULongLong(SPEC_PTS_ZIRCONIUM_REACTOR_METAMORPHOSIS);

	data.specPtsILMENITE_FURNACE_PRODUCTION = reader.getULongLong(SPEC_PTS_ILMENITE_FURNACE_PRODUCTION);
	data.specPtsILMENITE_FURNACE_METAMORPHOSIS = reader.getULongLong(SPEC_PTS_ILMENITE_FURNACE_METAMORPHOSIS);

	data.specPtsMAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED = reader.getULongLong(SPEC_PTS_MAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED);

	data.specPtsSUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED = reader.getULongLong(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED);
	data.specPtsSUBMERSIBLE_FILTRATION_TANK_RANGE = reader.getULongLong(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_RANGE);

	data.specPtsSUBMARINE_MINING_MACHINE_WINDING_SPEED = reader.getULongLong(SPEC_PTS_SUBMARINE_MINING_MACHINE_WINDING_SPEED);
	data.specPtsSUBMARINE_MINING_MACHINE_RANGE = reader.getULongLong(SPEC_PTS_SUBMARINE_MINING_MACHINE_RANGE);

	data.specPtsUNDERGROUND_DRILLING_MACHINE_WINDING_SPEED = reader.getULongLong(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_WINDING_SPEED);
	data.specPtsUNDERGROUND_DRILLING_MACHINE_RANGE = reader.getULongLong(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_RANGE);

	/** Real scientific points */
	
	data.realPtsQUARK_GLUON_CORE_SPEED = reader.getDouble(SCLEVEL_QUARK_GLUON_CORE_SPEED);
	data.realPtsQUARK_GLUON_CORE_CONSUMPTION = reader.getDouble(SCLEVEL_QUARK_GLUON_CORE_CONSUMPTION);

	data.realPtsNAVIGATION_COMPUTER_SPEED = reader.getDouble(SCLEVEL_NAVIGATION_COMPUTER_SPEED);

	data.realPtsSUBSPACE_BEACON_SPEED = reader.getDouble(SCLEVEL_SUBSPACE_BEACON_SPEED);

	data.realPtsINERTIAL_DAMPERS_SPEED = reader.getDouble(SCLEVEL_INERTIAL_DAMPERS_SPEED);

	data.realPtsIMPULS_ENGINE_FORCE = reader.getDouble(SCLEVEL_IMPULS_ENGINE_FORCE);
	data.realPtsIMPULS_ENGINE_CONSUMPTION = reader.getDouble(SCLEVEL_IMPULS_ENGINE_CONSUMPTION);

	data.realPtsMECHANICAL_DAMPERS_ACCELERATION = reader.getDouble(SCLEVEL_MECHANICAL_DAMPERS_ACCELERATION);

	data.realPtsDRONE_MISSILES_DAMAGE = reader.getDouble(SCLEVEL_DRONE_MISSILES_DAMAGE);
	data.realPtsDRONE_MISSILES_PRECISION = reader.getDouble(SCLEVEL_DRONE_MISSILES_PRECISION);
	data.realPtsDRONE_MISSILES_RANGE = reader.getDouble(SCLEVEL_DRONE_MISSILES_RANGE);

	data.realPtsDRONE_MISSILE_LAUNCHER_ACCUMULATOR = reader.getDouble(SCLEVEL_DRONE_MISSILE_LAUNCHER_ACCUMULATOR);
	data.realPtsDRONE_MISSILE_LAUNCHER_CHARGING = reader.getDouble(SCLEVEL_DRONE_MISSILE_LAUNCHER_CHARGING);

	data.realPtsSHIPS_LEVEL = reader.getDouble(SCLEVEL_SHIPS_LEVEL);

	data.realPtsBASES_LEVEL = reader.getDouble(SCLEVEL_BASES_LEVEL);

	data.realPtsHANGARS_LEVEL = reader.getDouble(SCLEVEL_HANGARS_LEVEL);

	data.realPtsANDROIDS_LEVEL = reader.getDouble(SCLEVEL_ANDROIDS_LEVEL);
	data.realPtsANDROIDS_CONSUMPTION = reader.getDouble(SCLEVEL_ANDROIDS_CONSUMPTION);

	data.realPtsENERGETIC_ACCUMULATOR_ACCUMULATOR = reader.getDouble(SCLEVEL_ENERGETIC_ACCUMULATOR_ACCUMULATOR);
	data.realPtsENERGETIC_ACCUMULATOR_CHARGING = reader.getDouble(SCLEVEL_ENERGETIC_ACCUMULATOR_CHARGING);

	data.realPtsMAINFRAME_BIO_NODES = reader.getDouble(SCLEVEL_MAINFRAME_BIO_NODES);
	data.realPtsMAINFRAME_PREDICTION = reader.getDouble(SCLEVEL_MAINFRAME_PREDICTION);
	data.realPtsMAINFRAME_TIME_REUSABILITY = reader.getDouble(SCLEVEL_MAINFRAME_TIME_REUSABILITY);
	data.realPtsMAINFRAME_CONSUMPTION = reader.getDouble(SCLEVEL_MAINFRAME_CONSUMPTION);

	data.realPtsSCIENTIFIC_LABS_LEVEL = reader.getDouble(SCLEVEL_SCIENTIFIC_LABS_LEVEL);

	data.realPtsLIFE_SUPPORT_CAPACITY = reader.getDouble(SCLEVEL_LIFE_SUPPORT_CAPACITY);
	data.realPtsLIFE_SUPPORT_CONSUMPTION = reader.getDouble(SCLEVEL_LIFE_SUPPORT_CONSUMPTION);

	data.realPtsWEAPON_ENERGY_CIRCUIT_CHARGING = reader.getDouble(SCLEVEL_WEAPON_ENERGY_CIRCUIT_CHARGING);

	data.realPtsTRANSPORT_BEAM_GENERATOR_ACCUMULATOR = reader.getDouble(SCLEVEL_TRANSPORT_BEAM_GENERATOR_ACCUMULATOR);
	data.realPtsTRANSPORT_BEAM_GENERATOR_CHARGING = reader.getDouble(SCLEVEL_TRANSPORT_BEAM_GENERATOR_CHARGING);
	data.realPtsTRANSPORT_BEAM_GENERATOR_FORCIBILITY = reader.getDouble(SCLEVEL_TRANSPORT_BEAM_GENERATOR_FORCIBILITY);
	data.realPtsTRANSPORT_BEAM_GENERATOR_PRECISION = reader.getDouble(SCLEVEL_TRANSPORT_BEAM_GENERATOR_PRECISION);
	data.realPtsTRANSPORT_BEAM_GENERATOR_RANGE = reader.getDouble(SCLEVEL_TRANSPORT_BEAM_GENERATOR_RANGE);

	data.realPtsLASER_GUN_ACCUMULATOR = reader.getDouble(SCLEVEL_LASER_GUN_ACCUMULATOR);
	data.realPtsLASER_GUN_CHARGING = reader.getDouble(SCLEVEL_LASER_GUN_CHARGING);
	data.realPtsLASER_GUN_FORCIBILITY = reader.getDouble(SCLEVEL_LASER_GUN_FORCIBILITY);
	data.realPtsLASER_GUN_PRECISION = reader.getDouble(SCLEVEL_LASER_GUN_PRECISION);
	data.realPtsLASER_GUN_RANGE = reader.getDouble(SCLEVEL_LASER_GUN_RANGE);

	data.realPtsDEFLECTOR_SHIELDS_GENERATOR_SOLIDITY = reader.getDouble(SCLEVEL_DEFLECTOR_SHIELDS_GENERATOR_SOLIDITY);
	data.realPtsDEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR = reader.getDouble(SCLEVEL_DEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR);
	data.realPtsDEFLECTOR_SHIELDS_GENERATOR_CHARGING = reader.getDouble(SCLEVEL_DEFLECTOR_SHIELDS_GENERATOR_CHARGING);

	data.realPtsHIGH_RESOLUTION_SENSORS_LEVEL = reader.getDouble(SCLEVEL_HIGH_RESOLUTION_SENSORS_LEVEL);
	data.realPtsHIGH_RESOLUTION_SENSORS_RANGE = reader.getDouble(SCLEVEL_HIGH_RESOLUTION_SENSORS_RANGE);
	data.realPtsHIGH_RESOLUTION_SENSORS_CONSUMPTION = reader.getDouble(SCLEVEL_HIGH_RESOLUTION_SENSORS_CONSUMPTION);

	data.realPtsLONG_RANGE_SENSORS_LEVEL = reader.getDouble(SCLEVEL_LONG_RANGE_SENSORS_LEVEL);
	data.realPtsLONG_RANGE_SENSORS_RANGE = reader.getDouble(SCLEVEL_LONG_RANGE_SENSORS_RANGE);
	data.realPtsLONG_RANGE_SENSORS_CONSUMPTION = reader.getDouble(SCLEVEL_LONG_RANGE_SENSORS_CONSUMPTION);

	data.realPtsCLOAKING_DEVICE_LEVEL = reader.getDouble(SCLEVEL_CLOAKING_DEVICE_LEVEL);
	data.realPtsCLOAKING_DEVICE_CONSUMPTION = reader.getDouble(SCLEVEL_CLOAKING_DEVICE_CONSUMPTION);

	data.realPtsPROBE_DEVICE_LEVEL = reader.getDouble(SCLEVEL_PROBE_DEVICE_LEVEL);

	data.realPtsMAGNETICAL_FILTER_PRODUCTION = reader.getDouble(SCLEVEL_MAGNETICAL_FILTER_PRODUCTION);

	data.realPtsDEUTERIUM_DECOMPOSER_PRODUCTION = reader.getDouble(SCLEVEL_DEUTERIUM_DECOMPOSER_PRODUCTION);
	data.realPtsDEUTERIUM_DECOMPOSER_METAMORPHOSIS = reader.getDouble(SCLEVEL_DEUTERIUM_DECOMPOSER_METAMORPHOSIS);

	data.realPtsZIRCONIUM_REACTOR_PRODUCTION = reader.getDouble(SCLEVEL_ZIRCONIUM_REACTOR_PRODUCTION);
	data.realPtsZIRCONIUM_REACTOR_METAMORPHOSIS = reader.getDouble(SCLEVEL_ZIRCONIUM_REACTOR_METAMORPHOSIS);

	data.realPtsILMENITE_FURNACE_PRODUCTION = reader.getDouble(SCLEVEL_ILMENITE_FURNACE_PRODUCTION);
	data.realPtsILMENITE_FURNACE_METAMORPHOSIS = reader.getDouble(SCLEVEL_ILMENITE_FURNACE_METAMORPHOSIS);

	data.realPtsMAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED = reader.getDouble(SCLEVEL_MAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED);

	data.realPtsSUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED = reader.getDouble(SCLEVEL_SUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED);
	data.realPtsSUBMERSIBLE_FILTRATION_TANK_RANGE = reader.getDouble(SCLEVEL_SUBMERSIBLE_FILTRATION_TANK_RANGE);

	data.realPtsSUBMARINE_MINING_MACHINE_WINDING_SPEED = reader.getDouble(SCLEVEL_SUBMARINE_MINING_MACHINE_WINDING_SPEED);
	data.realPtsSUBMARINE_MINING_MACHINE_RANGE = reader.getDouble(SCLEVEL_SUBMARINE_MINING_MACHINE_RANGE);

	data.realPtsUNDERGROUND_QUARRYING_WINDING_SPEED = reader.getDouble(SCLEVEL_UNDERGROUND_DRILLING_MACHINE_WINDING_SPEED);
	data.realPtsUNDERGROUND_QUARRYING_RANGE = reader.getDouble(SCLEVEL_UNDERGROUND_DRILLING_MACHINE_RANGE);

	data.totalTokens = reader.getULongLong(REQUEST_MAX_SCIENCE_PTS);

	mainWindow_->answerUpdateScienceTree(data);	
}

void CommandClient::updateFortressCentralInformation(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::ship_central_information(shipId));
}

void CommandClient::processUpdateFortressCentralInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_SHIP_CENTRAL_INFORMATION_SHIPID);
		std::string reason = reader.getString(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateCentralInformationFAIL(fortressId, reason);
		return;
	}

	CentralInfoDetails details;

	details.shipId = reader.getId(REQUEST_SHIP_CENTRAL_INFORMATION_SHIPID);
	details.structuralIntegrityActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SINTEGRITY_ACT);    
    details.structuralIntegrityTotal = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SINTEGRITY_MAX);    
	details.structuralIntegrityGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SINTEGRITY_GRADIENT);
	details.manoeuvrability = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_MAN);      

	details.width = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_WIDTH);             
    details.length = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_LENGTH);            
	details.height = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_HEIGHT);            
	details.weight = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_WEIGHT);   

	details.quarkGluonPlasmaActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_QGPLAZMA);     
	details.quarkGluonPlasmaFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_QGPLAZMA);  
	details.quarkGluonPlasmaGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_QGPLAZMA);  
	// Quark gluon plasma does not have capacity

	details.ulreaActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_ULREA);         
	details.ulreaGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_ULREA);    
	// Ulrei does not have capacity and free capacity

	details.heavyWaterActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_HWATER);        
    details.heavyWaterSize = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SIZE_HWATER);   
	details.heavyWaterFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_HWATER); 
	details.heavyWaterGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_HWATER);       

	details.deuteriumActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_DEUT);          
	details.deuteriumSize = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SIZE_DEUT);       
	details.deuteriumFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_DEUT);    
	details.deuteriumGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_DEUT);         

	details.zirconiumCrystalsActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_ZCRYSTAL);      
	details.zirconiumCrystalsSize = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SIZE_ZCRYSTAL); 
	details.zirconiumCrystalsFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_ZCRYSTAL); 
	details.zirconiumCrystalGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_ZCRYSTAL);  

	details.energyActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_ENERGY);        
	details.energyFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_ENERGY);     
	details.energyGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_ENERGY);   

	details.ilmeniteActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_ILMENITE);      
	details.ilmeniteSize = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SIZE_ILMENITE); 
	details.ilmeniteFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_ILMENITE); 
	details.ilmeniteGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_ILMENITE);     

	details.titaniumActual = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACT_TITANIUM);      
	details.titaniumSize = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_SIZE_TITANIUM);   
	details.titaniumFreeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY_TITANIUM);      
	details.titaniumGradient = reader.getDouble(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_GRAD_TITANIUM);   	

	details.weightWithCargo = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_WEIGHT_WITH_CARGO);
	details.loadingWeightLimit = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_LOADING_WEIGHT_LIMIT);
	details.loadingCapacityLimit = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_LOADING_CAPACITY_LIMIT);
	details.actualTotalCargoWeight = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ACTUAL_TOTAL_CARGO_WEIGHT);;
	details.freeWeight = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_WEIGHT);
	details.actualSizeOfCargoInWarehouse = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_CARGO_SIZE);
	details.freeCapacity = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_CAPACITY);

	details.freeResWeight = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_RES_WEIGHT);
	details.commonRawMaterialCapacityLimit = reader.getULongLong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_FREE_RES_CAPACITY);
	details.heavyWaterDensity = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_HEAVY_WATER_DENSITY);
	details.deuteriumDensity = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_DEUTERIUM_DENSITY);
	details.zirconiumCrystalDensity = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ZIRCONIUM_CRYSTAL_DENSITY);;
	details.ilmeniteDensity = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_ILMENITE_DENSITY);
	details.titaniumDensity = reader.getULong(REQUEST_SHIP_CENTRAL_INFORMATION_ANSWER_TITANIUM_DENSITY);

	mainWindow_->answerUpdateCentralInformation(details);
}

void CommandClient::updateFortressShieldsInformation(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_shields_information(shipId));
}

void CommandClient::processUpdateFortressShieldsInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);
	
	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_SHIELDS_INFORMATION_FORTRESSID);
		std::string reason = reader.getString(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateShieldsInformationFAIL(fortressId, reason);
		return;
	}

	ShieldsDetails details;

	details.shipId = reader.getId(REQUEST_FORTRESS_SHIELDS_INFORMATION_FORTRESSID);
	details.damageStatus = reader.getDouble(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_STATUS);	
	details.solidityActual = reader.getULong(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_SOLIDITY);
	details.energyActual = reader.getULongLong(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_ENERGY);
	details.accumulatorActual = reader.getULong(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_ACCUMULATOR);	
	details.chargingSpeedActual = reader.getULong(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_CHARGING);
	details.chargingLimit = reader.getDouble(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_TARGET_ENERGY);				
	details.energyConsumptionActual = reader.getDouble(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_CONSUMPTION);
	details.energyLeakActual = reader.getDouble(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_LEAK);
	details.avalDeflectorShields = reader.getBool(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_AVAILABLE);
	details.gradient = reader.getDouble(REQUEST_FORTRESS_SHIELDS_INFORMATION_ANSWER_GRADIENT);

	mainWindow_->answerUpdateShieldsInformation(details);
}

void CommandClient::processUpdateDeviceEnergyStateFAIL(const ValueReader & reader) {
    
	id_t shipId = reader.getId(REQUEST_DEVICE_ENERGY_STATE_ANSWER_FORTRESSID);
	std::string reason = reader.getString(REQUEST_DEVICE_ENERGY_STATE_ANSWER_FAIL_REASON);

	mainWindow_->answerUpdateDeviceEnergyStateFAIL(shipId, reason);
}

void CommandClient::updateShipImpulsDriveInformation(id_t shipId) {	
	socketClient_->sendAndFreeMessage(requestWriter::ship_impulse_drive_information(shipId));
}

void CommandClient::processUpdateShipImpulsDriveInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t shipId = reader.getId(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_SHIPID);
		std::string reason = reader.getString(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateImpulsDriveInformationFAIL(shipId, reason);
		return;
	}

	impulse_drive_status details;

	id_t shipId = reader.getId(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_SHIPID);
	details.actualJetForce = reader.getDouble(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_ACTUAL_JET_FORCE);	
	details.actualConsumption = reader.getULong(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_ACTUAL_CONSUMPTION);
	details.mechanical_dampers_max_acceleration = reader.getULongLong(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_MECHANICAL_DAMPERS_MAX_ACCELERATION);
	details.mechanical_dampers_status = reader.getULong(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_MECHANICAL_DAMPERS_STATUS);	
	details.mechanical_dampers_available = reader.getBool(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_MECHANICAL_DAMPERS_AVAILABLE);	
	details.impulse_jet_engine_actual_force = reader.getULong(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_IMPULSE_JET_ENGINE_ACTUAL_FORCE);
	details.impulse_jet_engine_actual_consumption = reader.getDouble(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_IMPULSE_JET_ENGINE_ACTUAL_CONSUMPTION);				
	details.impulse_jet_engine_status = reader.getDouble(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_IMPULSE_JET_ENGINE_STATUS);
	details.impulse_jet_engine_available = reader.getBool(REQUEST_SHIP_IMPULSE_DRIVE_INFORMATION_ANSWER_IMPULSE_JET_ENGINE_AVAILABLE);

	mainWindow_->answerUpdateImpulsDriveInformation(shipId, details);
}

void CommandClient::updateShipSubspaceDriveInformation(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::ship_subspace_drive_information(shipId));
}

void CommandClient::processUpdateShipSubspaceDriveInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t shipId = reader.getId(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_SHIPID);
		std::string reason = reader.getString(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateSubspaceDriveInformationFAIL(shipId, reason);
		return;
	}

	subspace_drive_status details;

	id_t shipId = reader.getId(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_SHIPID);
	details.navigation_computer_max_speed = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_NAVIGATION_COMPUTER_MAX_SPEED);	
	details.navigation_computer_status = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_NAVIGATION_COMPUTER_STATUS);
	details.navigation_computer_available = reader.getBool(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_NAVIGATION_COMPUTER_AVAILABLE);
	details.inertial_dampers_max_speed = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_INTERTIAL_DAMPERS_MAX_SPEED);
	details.inertial_dampers_status = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_INTERTIAL_DAMPERS_STATUS);	
	details.inertial_dampers_available = reader.getBool(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_INTERTIAL_DAMPERS_AVAILABLE);
	details.subspace_beacon_max_speed = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_SUBSPACE_BEACON_MAX_SPEED);
	details.subspace_beacon_status = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_SUBSPACE_BEACON_STATUS);				
	details.subspace_beacon_available = reader.getBool(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_SUBSPACE_BEACON_AVAILABLE);
	details.quark_gluon_core_max_speed = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_QUARK_GLUON_CORE_MAX_SPEED);
	details.quark_gluon_core_consumption = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_QUARK_GLUON_CORE_CONSUMPTION);
	details.quark_gluon_core_status = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_QUARK_GLUON_CORE_STATUS);
	details.quark_gluon_core_available = reader.getBool(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_QUARK_GLUON_CORE_AVAILABLE);

	details.actualConsumption = reader.getULong(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_CONSUMPTION);
	details.actualSpeedToC = reader.getDouble(REQUEST_SHIP_SUBSPACE_DRIVE_INFORMATION_ANSWER_SPEED_TOC);
	
	mainWindow_->answerUpdateSubspaceDriveInformation(shipId, details);
}

void CommandClient::updateFortressMainframeInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_mainframe_information(fortressId));
}

void CommandClient::processUpdateFortressMainframeInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_MAINFRAME_INFORMATION_FORTRESSID);
		std::string reason = reader.getString(REQUEST_FORTRESS_MAINFRAME_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateMainframeInformationFAIL(fortressId, reason);
		return;
	}

	mainframe_status state;

	id_t fortressId = reader.getId(REQUEST_FORTRESS_MAINFRAME_INFORMATION_FORTRESSID);
	state.actualBioNodes = reader.getULongLong(REQUEST_FORTRESS_MAINFRAME_INFORMATION_ACTUAL_BIONODES);
	state.actualConsumption = reader.getDouble(REQUEST_FORTRESS_MAINFRAME_INFORMATION_ACTUAL_CONSUMPTION);
	state.actualPrediction = reader.getULongLong(REQUEST_FORTRESS_MAINFRAME_INFORMATION_ACTUAL_PREDICTION);
	state.actualTimeReusability = reader.getULongLong(REQUEST_FORTRESS_MAINFRAME_INFORMATION_ACTUAL_TIME_REUSABILITY);
	state.status = reader.getDouble(REQUEST_FORTRESS_MAINFRAME_INFORMATION_STATUS);

	mainWindow_->answerUpdateMainframeInformation(fortressId, state);
}

void CommandClient::updateFortressWeaponsInformation(id_t shipId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_weapons_information(shipId));	
}

void CommandClient::shipLocationInfo(id_t shipId)
{
	socketClient_->sendAndFreeMessage( requestWriter::ship_location_information( shipId ) );
}

void CommandClient::processShipLocationInfo( message * protocolMessage )
{
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		return;
	}

	location_status state;

	id_t shipId = reader.getId( REQUEST_SHIP_LOCATION_INFORMATION_SHIPID );
	state.actualSpaceObject = reader.getId( REQUEST_SHIP_LOCATION_INFORMATION_SPACE_OBJECT_ACT_IN );
	state.nearestStar = reader.getId( REQUEST_SHIP_LOCATION_INFORMATION_NEAREST_STAR );
	state.actualStar = reader.getId( REQUEST_SHIP_LOCATION_INFORMATION_STAR_IN );

	
	mainWindow_->answerShipLocation( shipId, state );
}

void CommandClient::processUpdateFortressWeaponsInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t shipId = reader.getId(REQUEST_FORTRESS_WEAPONS_INFORMATION_FORTRESSID);
		std::string reason = reader.getString(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateWeaponsInformationFAIL(shipId, reason);
		return;
	}

	weapons_status details;

	id_t shipId = reader.getId(REQUEST_FORTRESS_WEAPONS_INFORMATION_FORTRESSID);
	details.weapon_energy_circuit_charging = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_ENERGY_CIRTUIT_CHARGING);
	details.weapon_energy_circuit_client_charging = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_ENERGY_CIRTUIT_CLIENT_CHARGING);
	
	details.weapon_energy_circuit_status = reader.getDouble(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_ENERGY_CIRCUIT_STATUS);
	details.weapon_distance_to_the_weapons_target = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DISTANCE_TO_THE_WEAPONS_TARGET);
	details.weapon_total_charging = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_TOTAL_CHARGING);
	details.weapon_actual_energy_consumption = reader.getDouble(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_ACTUAL_ENERGY_CONSUMPTION);
	details.drone_missiles_actual_launch = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_ACTUAL_LAUNCH);
	details.drone_missiles_actual_range = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_ACTUAL_RANGE);
	details.drone_missiles_actual_precision = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_ACTUAL_PRECISION);
	details.drone_missiles_actual_damage = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_ACTUAL_DAMAGE);
	details.drone_missiles_count = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_COUNT);
	details.drone_missiles_working = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_WORKING);
	details.drone_missiles_damaged = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_WEAPON_DRONE_MISSILES_DAMAGED);

	details.avalWeaponEnergyCircuit = reader.getBool(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_AVAL_WEAPON_ENERGY_CIRCUIT);
	details.avalLaserGuns = reader.getBool(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_AVAL_LASER_GUNS);
	details.avalDroneMissileLaunchers = reader.getBool(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_AVAL_DRONE_MISSILE_LAUNCHERS);
	details.avalDroneMissiles = reader.getBool(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_AVAL_DRONE_MISSILES);

	details.max_drone_missile_launchers = reader.getULong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_MAX_DRONE_MISSILE_LAUNCHERS);
	details.max_laser_guns = reader.getULong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_MAX_LASER_GUNS);
	
	unsigned long laserGunCount = reader.getULong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_COUNT);

	for (int i = 1; i < laserGunCount + 1; ++i) {
		laser_gun_status laserGun;
		readLaserGun(reader, i, laserGun);
		details.laser_guns.push_back(laserGun);
	}

	unsigned long droneLauncherCount = reader.getULong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_COUNT);

	for (int i = 1; i < droneLauncherCount + 1; ++i) {
		drone_missile_launcher_status droneLauncher;
		readDroneMissileLauncher(reader, i, droneLauncher);
		details.drone_missile_launchers.push_back(droneLauncher);
	}

	mainWindow_->answerUpdateWeaponsInformation(shipId, details);
}

void CommandClient::readDroneMissileLauncher(ValueReader & reader, int index, drone_missile_launcher_status & details)
{
	details.energy = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_ENERGY, index);
	details.targetEnergy = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_TARGET_ENERGY, index);
	details.actualAccumulator = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_ACTUAL_ACCUMULATOR, index);
	details.status = reader.getDouble(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_STATUS, index);
	details.index = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_INDEX, index);
	details.id = reader.getId(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_ID, index);
	details.gradient = reader.getDouble(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_DRONE_LAUNCHER_GRADIENT, index);
}

void CommandClient::readLaserGun(ValueReader & reader, int index, laser_gun_status & details)
{
	details.energy = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_ENERGY, index);
	details.targetEnergy = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_TARGET_ENERGY, index);
	details.actualAccumulator = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_ACTUAL_ACCUMULATOR, index);
	details.actualRange = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_ACTUAL_RANGE, index);
	details.actualPrecision = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_ACTUAL_PRECISION, index);
	details.actualForcibility = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_ACTUAL_FORCIBILITY, index);
	details.status = reader.getDouble(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_STATUS, index);
	details.index = reader.getULongLong(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_INDEX, index);
	details.id = reader.getId(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_ID, index);
	details.gradient = reader.getDouble(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_LASER_GUN_GRADIENT, index);
}

void CommandClient::changeFortressWeaponsState(id_t shipId, WeaponsChangeDetails & state) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_set_weapons(shipId, state.droneGuns, state.laserGuns));
}

void CommandClient::processChangeFortressWeaponsStateFAIL(ValueReader & reader) {

	id_t fortressId = reader.getId(REQUEST_FORTRESS_WEAPONS_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_FORTRESS_WEAPONS_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerChangeWeaponsInformationFAIL(fortressId, fail);
}

void CommandClient::processUpdateFortressCrewInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_CREW_INFORMATION_FORTRESSID);
		std::string reason = reader.getString(REQUEST_FORTRESS_CREW_INFORMATION_ANSWER_FAIL);
		mainWindow_->answerUpdateCrewInformationFAIL(fortressId, reason);
		return;
	}

	crew_status state;

	id_t fortressId = reader.getId(REQUEST_FORTRESS_CREW_INFORMATION_FORTRESSID);

	state.ABLE_CREW_CAPITAN = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_CAPITAN);
	state.ABLE_CREW_DOCTOR = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_DOCTOR);
	state.ABLE_CREW_OFFICER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_OFFICER);
	state.ABLE_CREW_ENGINEER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_ENGINEER);
	state.ABLE_CREW_PILOT = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_PILOT);
	state.ABLE_CREW_SCIENTIST = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_SCIENTIST);
	state.ABLE_CREW_PASSENGER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ABLE_CREW_PASSENGER);

	state.WOUNDED_CREW_CAPITAN = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_CAPITAN);
	state.WOUNDED_CREW_DOCTOR = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_DOCTOR);
	state.WOUNDED_CREW_OFFICER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_OFFICER);
	state.WOUNDED_CREW_ENGINEER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_ENGINEER);
	state.WOUNDED_CREW_PILOT = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_PILOT);
	state.WOUNDED_CREW_SCIENTIST = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_SCIENTIST);
	state.WOUNDED_CREW_PASSENGER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_WOUNDED_CREW_PASSENGER);

	state.TOTAL_CREW_CAPITAN = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_CAPITAN);
	state.TOTAL_CREW_DOCTOR = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_DOCTOR);
	state.TOTAL_CREW_OFFICER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_OFFICER);
	state.TOTAL_CREW_ENGINEER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_ENGINEER);
	state.TOTAL_CREW_PILOT = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_PILOT);
	state.TOTAL_CREW_SCIENTIST = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_SCIENTIST);
	state.TOTAL_CREW_PASSENGER = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_TOTAL_CREW_PASSENGER);

	state.ACT_PEOPLE_WEIGHT = reader.getULongLong(REQUEST_FORTRESS_CREW_INFORMATION_ACT_PEOPLE_WEIGHT);

	mainWindow_->answerUpdateCrewInformation(fortressId, state);
}

void CommandClient::updateFortressCrewInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_crew_information(fortressId));
}

void CommandClient::processUpdateShip(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	id_t shipId = reader.getId(UPDATE_SHIP_ID);
	mainWindow_->answerUpdateShip(shipId); 
}

void CommandClient::processUpdateFortressQuarryInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processUpdateFortressQuarryInformationFAIL(reader);
		return;
	}

	quarry_status state;

	id_t fortressId = reader.getId(REQUEST_FORTRESS_QUARRY_INFORMATION_FORTRESSID);

	state.QuarkGluonPlasmaQuarryingSpeed = reader.getDouble(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_QGP_SPEED);
	state.HeavyWaterQuarryingSpeed = reader.getDouble(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_HWA_SPEED);
	state.ZirconiumCrystalQuarryingSpeed = reader.getDouble(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ZRC_SPEED);
	state.IlmeniteQuarryingSpeed = reader.getDouble(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ILM_SPEED);

    state.isPossibleToQuarryQuarkGluonPlasma = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ISP_QGP);
	state.isPossibleToQuarryHeavyWater = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ISP_HWA);
	state.isPossibleToQuarryZirconiumCrystals = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ISP_ZRC);
	state.isPossibleToQuarryIlmenite = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ISP_ILM);

	state.isActuallyQuarryingQuarkGluonPlasma = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_IAQ_QGP);
	state.isActuallyQuarryingHeavyWater = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_IAQ_HWA);
	state.isActuallyQuarryingZirconiumCrystals = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_IAQ_ZRC);
	state.isActuallyQuarryingIlmenite = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_IAQ_ILM);

	state.QuarkGluonPlasmaQuarryingCount = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_QGP_COUNT);
	state.HeavyWaterQuarryingCount = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_HWA_COUNT);
	state.ZirconiumCrystalQuarryingCount = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ZRC_COUNT);
	state.IlmeniteQuarryingCount = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ILM_COUNT);

	state.QuarkGluonPlasmaQuarryingWorking = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_QGP_WORKING);
	state.HeavyWaterQuarryingWorking = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_HWA_WORKING);
	state.ZirconiumCrystalQuarryingWorking = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ZRC_WORKING);
	state.IlmeniteQuarryingWorking = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ILM_WORKING);

	state.QuarkGluonPlasmaQuarryingDamaged = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_QGP_DAMAGED);
	state.HeavyWaterQuarryingDamaged = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_HWA_DAMAGED);
	state.ZirconiumCrystalQuarryingDamaged = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ZRC_DAMAGED);
	state.IlmeniteQuarryingDamaged = reader.getULongLong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ILM_DAMAGED);

	state.QuarkGluonPlasmaQuarryingActualRange = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_QGP_ACT_RANGE);
	state.HeavyWaterQuarryingActualRange = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_HWA_ACT_RANGE);
	state.ZirconiumCrystalQuarryingActualRange = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ZRC_ACT_RANGE);
	state.IlmeniteQuarryingActualRange = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ILM_ACT_RANGE);

	state.QuarkGluonPlasmaQuarryingActualMaximalSpeed = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_QGP_MAX_SPEED);
	state.HeavyWaterQuarryingActualMaximalSpeed = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_HWA_MAX_SPEED);
	state.ZirconiumCrystalQuarryingActualMaximalSpeed = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ZRC_MAX_SPEED);
	state.IlmeniteQuarryingActualMaximalSpeed = reader.getULong(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_ILM_MAX_SPEED);

	state.avalMagneticalCollectorsOfPlasma = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_AVAL_MAGNETICAL_COLLECTORS);
	state.avalSubmarineMiningMachine = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_AVAL_SUBMARINE_MINING_MACHINE);
	state.avalSubmersibleFiltrationTank = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_AVAL_SUBMERSIBLE_FILTRATION_TANK);
	state.avalUndergroundDrillingMachine = reader.getBool(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_AVAL_UNDERGROUND_DRILLING_MACHINE);

	mainWindow_->answerUpdateQuarryInformation(fortressId, state);
}

void CommandClient::processUpdateFortressQuarryInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_FORTRESS_QUARRY_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_FORTRESS_QUARRY_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateQuarryInformationFAIL(fortressId, fail);
}

void CommandClient::updateFortressQuarryInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_quarry_info(fortressId));
}

void CommandClient::changeQuarkGluonPlasmaQuarryState(id_t fortressId, bool isQuarrying) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_quarry_change_state(fortressId, PQT_QuarkGluonPlasma, isQuarrying));
}

void CommandClient::changeHeavyWaterQuarryState(id_t fortressId, bool isQuarrying) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_quarry_change_state(fortressId, PQT_HeavyWater, isQuarrying));
}

void CommandClient::changeZirconiumCrystalQuarryState(id_t fortressId, bool isQuarrying) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_quarry_change_state(fortressId, PQT_ZirconiumCrystal, isQuarrying));
}

void CommandClient::changeIlmeniteQuarryState(id_t fortressId, bool isQuarrying) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_quarry_change_state(fortressId, PQT_Ilmenite, isQuarrying));
}

void CommandClient::processChangeFortressQuarryStateFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_FORTRESS_QUARRY_CHANGE_STATE_FORTRESS_ID);
	std::string fail = reader.getString(REQUEST_FORTRESS_QUARRY_CHANGE_STATE_ANSWER_FAIL);

	mainWindow_->answerChangeQuarryStateFAIL(fortressId, fail);
}

void CommandClient::updateFortressAccommodationsInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_accommodations_information(fortressId));
}

void CommandClient::processUpdateFortressAccommodationsInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateAccommodationsInformationFAIL(fortressId, fail);
}

void CommandClient::processUpdateFortressAccommodationsInformation(message * protocolMessage) {
    
	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processUpdateFortressAccommodationsInformationFAIL(reader);
		return;
	}

	accommodation_status state;

	id_t fortressId = reader.getId(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_FORTRESSID);

	state.accommodationsSize = reader.getULongLong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_ACCOMMODATIONS_SIZE);
	state.accommodationsWeight = reader.getULongLong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_ACCOMMODATIONS_WEIGHT);

	state.comfortableRoomsCount = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_COMFORTABLE_ROOMS_COUNT);
	state.commonCabinsCount = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_COMMON_CABINS_COUNT);
	state.luxuryAccommodationsCount = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_LUXURY_ACCOMMODATIONS_COUNT);
	state.warehousesWithLifeSupportCount = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_WAREHOUSES_WITH_LIFESUPPORT_COUNT);

	state.freeComfortableRooms = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_FREE_COMFORTABLE_ROOMS);
	state.freeCommonCabins = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_FREE_COMMON_CABINS);
	state.freeLuxuryAccommodations = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_FREE_LUXURY_ACCOMMODATIONS);
	state.freeWarehousesWithLifeSupport = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_FREE_WAREHOUSES_WITH_LIFESUPPORT);

	state.comfortableRoomsPrice = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_COMFORTABLE_ROOMS_PRICE);
	state.commonCabinsPrice = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_COMMON_CABINS_PRICE);
	state.luxuryAccommodationsPrice = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_LUXURY_ACCOMMODATIONS_PRICE);
	state.warehousesWithLifeSupportPrice = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_WAREHOUSES_WITH_LIFESUPPORT_PRICE);

	state.totalPoints = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_TOTAL_POINTS);
	state.consumedPoints = reader.getULong(REQUEST_FORTRESS_ACCOMMODATIONS_INFORMATION_CONSUMED_POINTS);

	mainWindow_->answerUpdateAccommodationsInformation(fortressId, state);
}

void CommandClient::updateFortressOtherEquipmentInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_other_equipment_information(fortressId));
}

void CommandClient::processUpdateFortressOtherEquipmentInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateOtherEquipmentInformationFAIL(fortressId, fail);
}

void CommandClient::processUpdateFortressOtherEquipmentInformation(message * protocolMessage) {
    
	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processUpdateFortressOtherEquipmentInformationFAIL(reader);
		return;
	}

	other_equipment_status state;

	id_t fortressId = reader.getId(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_FORTRESSID);

	state.actualEnergyConsumption = reader.getDouble(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_ACT_ENERGY_CONSUMPTION);
	state.otherEquipmentWeight = reader.getULongLong(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_OTHER_EQUIPMENT_WEIGHT);

	state.isLifeSupportAvailable = reader.getBool(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_LIFE_SUPPORT_AVAILABLE);
	state.isPlasmaFilterAvailable = reader.getBool(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_PLASMA_FILTER_AVAILABLE);
	state.isScietificLabAvailable = reader.getBool(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SCIENTIFIC_LAB_AVAILABLE);
	state.isSubspaceTransmitterAvailable = reader.getBool(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SUBSPACE_TRANSMITTER_AVAILABLE);

	state.lifeSupportActualCapacity = reader.getULong(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_LIFE_SUPPORT_CAPACITY);
	state.lifeSupportActualConsumption = reader.getDouble(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_LIFE_SUPPORT_ACT_CONSUMPTION);
	state.lifeSupportStatus = reader.getDouble(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_LIFE_SUPPORT_STATUS);

	state.scientificLabActualCapacity = reader.getULong(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SCIENTIFIC_LAB_ACT_CAPACITY);
	state.scientificLabActualLevel = reader.getULong(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SCIENTIFIC_LAB_ACT_LEVEL);
	state.scientificLabStatus = reader.getDouble(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SCIENTIFIC_LAB_STATUS);

	state.plasmaFilterActualTotalFilteringSpeed = reader.getULong(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_PLASMA_FILTER_ACT_TOTAL_FILTERING_SPEED);
	state.plasmaFilterStatus = reader.getDouble(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_PLASMA_FILTER_STATUS);

	state.subspaceTransmitterActualMessageCost = reader.getULong(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SUBSPACE_TRANSMITTER_MESSAGE_COST);
	state.subspaceTransmitterStatus = reader.getDouble(REQUEST_FORTRESS_OTHER_EQUIPMENT_INFORMATION_SUBSPACE_TRANSMITTER_STATUS);

	mainWindow_->answerUpdateOtherEquipmentInformation(fortressId, state);
}

void CommandClient::updateBaseFactoriesInformation(id_t baseId) {
	socketClient_->sendAndFreeMessage(requestWriter::base_factories_information(baseId));
}

void CommandClient::processUpdateBaseFactoriesInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_BASE_FACTORIES_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_BASE_FACTORIES_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateFactoriesInformationFAIL(fortressId, fail);
}

void CommandClient::processUpdateBaseFactoriesInformation(message * protocolMessage) {
    
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processUpdateBaseFactoriesInformationFAIL(reader);
		return;
	}

	factories_status state;

	id_t fortressId = reader.getId(REQUEST_BASE_FACTORIES_INFORMATION_FORTRESSID);

	state.factoriesSize = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_SIZE);
	state.factoriesWeight = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_WEIGHT);

	state.deuteriumDecomposer.isAvailable = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_AVAILABLE);
	state.deuteriumDecomposer.actualMetamorphosisEffectivity = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_ACTUAL_METAMORPHOSIS_EFFECTIVITY);
	state.deuteriumDecomposer.actualSpaceMetamorphosisEffectivity = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_ACTUAL_SPACE_METAMORPHOSIS_EFFECTIVITY);
	state.deuteriumDecomposer.actualTotalConsumption = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_ACTUAL_TOTAL_CONSUMPTION);
	state.deuteriumDecomposer.actualTotalProduction = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_ACTUAL_TOTAL_PRODUCTION);
	state.deuteriumDecomposer.count = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_COUNT);
	state.deuteriumDecomposer.damaged = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_DAMAGED);
	state.deuteriumDecomposer.working = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_DEUTERIUM_DECOMPOSER_WORKING);
								
	state.ilmeniteFurnace.isAvailable = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_AVAILABLE);
	state.ilmeniteFurnace.actualMetamorphosisEffectivity = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_ACTUAL_METAMORPHOSIS_EFFECTIVITY);
	state.ilmeniteFurnace.actualSpaceMetamorphosisEffectivity = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_ACTUAL_SPACE_METAMORPHOSIS_EFFECTIVITY);
	state.ilmeniteFurnace.actualTotalConsumption = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_ACTUAL_TOTAL_CONSUMPTION);
	state.ilmeniteFurnace.actualTotalProduction = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_ACTUAL_TOTAL_PRODUCTION);
	state.ilmeniteFurnace.count = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_COUNT);
	state.ilmeniteFurnace.damaged = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_DAMAGED);
	state.ilmeniteFurnace.working = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ILMENITE_FURNACE_WORKING);
								
	state.magneticalFilter.isAvailable = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_MAGNETICAL_FILTER_AVAILABLE);
	state.magneticalFilter.actualTotalProduction = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_MAGNETICAL_FILTER_ACTUAL_TOTAL_PRODUCTION);
	state.magneticalFilter.count = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_MAGNETICAL_FILTER_COUNT);
	state.magneticalFilter.damaged = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_MAGNETICAL_FILTER_DAMAGED);
	state.magneticalFilter.working = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_MAGNETICAL_FILTER_WORKING);
							
	state.zirconiumReactor.isAvailable = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_AVAILABLE);
	state.zirconiumReactor.actualMetamorphosisEffectivity = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_ACTUAL_METAMORPHOSIS_EFFECTIVITY);
	state.zirconiumReactor.actualSpaceMetamorphosisEffectivity = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_ACTUAL_SPACE_METAMORPHOSIS_EFFECTIVITY);
	state.zirconiumReactor.actualTotalConsumption = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_ACTUAL_TOTAL_CONSUMPTION);
	state.zirconiumReactor.actualTotalProduction = reader.getULong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_ACTUAL_TOTAL_PRODUCTION);
	state.zirconiumReactor.count = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_COUNT);
	state.zirconiumReactor.damaged = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_DAMAGED);
	state.zirconiumReactor.working = reader.getULongLong(REQUEST_BASE_FACTORIES_INFORMATION_ZIRCONIUM_REACTOR_WORKING);

	mainWindow_->answerUpdateFactoriesInformation(fortressId, state);
}

void CommandClient::updateFortressWarehousesInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_warehouses_information(fortressId));
}

void CommandClient::updateShipAndroidsInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::ship_androids_information(fortressId));
}

void CommandClient::updateBaseAndroidsInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::base_androids_information(fortressId));
}

void CommandClient::processUpdateFortressWarehousesInformation(message * protocolMessage) {
	// TODO Communication

	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processUpdateFortressWarehousesInformationFAIL(reader);
		return;
	}

	warehouses_status state;
	
	id_t fortressId = reader.getId(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_FORTRESSID);

	state.size = reader.getULong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_SIZE);
	state.weight = reader.getULong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_WEIGHT);

	state.energeticCell.isAvailable = reader.getBool(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ENERGETIC_CELL_AVAILABLE);
	state.energeticCell.actualCapacity = reader.getULong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ENERGETIC_CELL_CAPACITY);
	state.energeticCell.working = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ENERGETIC_CELL_WORKING);
	state.energeticCell.damaged = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ENERGETIC_CELL_DAMAGED);
	state.energeticCell.count = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ENERGETIC_CELL_COUNT);

	state.magneticGrid.isAvailable = reader.getBool(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_MAGNETIC_GRID_AVAILABLE);
	state.magneticGrid.actualCapacity = reader.getULong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_MAGNETIC_GRID_CAPACITY);
	state.magneticGrid.working = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_MAGNETIC_GRID_WORKING);
	state.magneticGrid.damaged = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_MAGNETIC_GRID_DAMAGED);
	state.magneticGrid.count = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_MAGNETIC_GRID_COUNT);

	state.transportContainer.isAvailable = reader.getBool(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_TRANSPORT_CONTAINER_AVAILABLE);
	state.transportContainer.actualCapacity = reader.getULong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_TRANSPORT_CONTAINER_CAPACITY);
	state.transportContainer.working = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_TRANSPORT_CONTAINER_WORKING);
	state.transportContainer.damaged = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_TRANSPORT_CONTAINER_DAMAGED);
	state.transportContainer.count = reader.getULongLong(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_TRANSPORT_CONTAINER_COUNT);

	readWarehouseItemsList(reader, REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ITEMS_PREFIX, state.warehouseItems);

	mainWindow_->answerUpdateWarehousesInformation(fortressId, state);
}

void CommandClient::readWarehouseItemsList(ValueReader & reader, const std::string & prefix, warehouses_status::items_list_t & itemsList) {
	unsigned long itemCount = reader.getULong(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_COUNT));

	for (int itemIndex = 1; itemIndex <= itemCount; ++itemIndex) {
		warehouse_item_status item;
		readWarehouseItem(reader, prefix, itemIndex, item);
		itemsList.push_back(item);
	}
}

void CommandClient::readWarehouseItem(ValueReader& reader, const std::string & prefix, int index, warehouse_item_status& item) {
	item.patternName = reader.getString(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_NAME, index));
	item.id = reader.getId(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_ID, index));
	item.working = reader.getULongLong(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_WORKING, index));
	item.damaged = reader.getULongLong(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_DAMAGED, index));
	item.isStackable = reader.getBool(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_STACKABLE, index));

	unsigned long paramCount = reader.getULong(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_PARAM_COUNT, index));

	for (int paramIndex = 1; paramIndex <= paramCount; ++paramIndex) {
		warehouse_item_status::parameter_t param;
		param.name = reader.getString(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_PARAM_NAME, index, paramIndex));
		param.value = reader.getString(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_PARAM_VALUE, index, paramIndex));
		param.type = (warehouse_parameter_type) reader.getULong(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_PARAM_TYPE, index, paramIndex));
		param.scienceIndependent = reader.getBool(create_param_name(prefix, WAREHOUSES_ITEM_STATUS_PARAM_SCIENCE_INDEPENDENT, index, paramIndex));

		item.parameters.push_back(param);
	}
}

void CommandClient::processUpdateFortressWarehousesInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_FORTRESS_WAREHOUSES_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateWarehousesInformationFAIL(fortressId, fail);
}

void CommandClient::processUpdateShipAndroidsInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processUpdateShipAndroidsInformationFAIL(reader);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_SHIP_ANDROIDS_INFORMATION_FORTRESSID);

	ship_androids_status state;

	readAndroidsStatus(reader, state);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_IMPULSDRIVE, state.impulsDrive);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_SUBSPACEDRIVE, state.subspaceDrive);	

	mainWindow_->answerUpdateShipAndroidsInformation(fortressId, state);
}

void CommandClient::processUpdateBaseAndroidsInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processUpdateBaseAndroidsInformationFAIL(reader);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_BASE_ANDROIDS_INFORMATION_FORTRESSID);

	base_androids_status state;

	readAndroidsStatus(reader, state);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_FACTORIES, state.factories);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_HANGARS, state.hangars);	

	mainWindow_->answerUpdateBaseAndroidsInformation(fortressId, state);
}

void CommandClient::readAndroidsStatus(ValueReader& reader, androids_status & details) {
	
	details.clientAndroidsStateSliderMax = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_ANDROIDS_STATE_SLIDER_MAX);
	details.clientAndroidsStateSliderBackground = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_ANDROIDS_STATE_SLIDER_BACKGROUND);
	details.clientWorkingAndroidsSliderMax = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_WORKING_ANDROIDS_SLIDER_MAX);
	details.clientWorkingAndroidsSliderValue = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_WORKING_ANDROIDS_SLIDER_VALUE);
	details.clientWorkingAndroidsSliderBackground = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_WORKING_ANDROIDS_SLIDER_BACKGROUND);
	details.clientRepConSliderMax = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_REPCON_SLIDER_MAX);
	details.clientRepConSliderValue = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_REPCON_SLIDER_VALUE);
	details.clientRepConSliderBackground = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_CLIENT_REPCON_SLIDER_BACKGROUND);

	details.actualWorkingAndroids = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_ACTUAL_WORKING_ANDROIDS);
	details.actualRepairingAndroids = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_ACTUAL_REPAIRING_ANDROIDS);
	details.actualConstructingAndroids = reader.getULongLong(REQUEST_FORTRESS_ANDRODIS_INFORMATION_ACTUAL_CONSTRUCTING_ANDROIDS);

	details.androidsMinPriority = reader.getULong(REQUEST_FORTRESS_ANDROIDS_INFORMATION_ANDROIDS_MIN_PRIORITY);
	details.androidsMaxPriority = reader.getULong(REQUEST_FORTRESS_ANDROIDS_INFORMATION_ANDROIDS_MAX_PRIORITY);

	details.androidsMinRatio = reader.getULong(REQUEST_FORTRESS_ANDROIDS_INFORMATION_ANDROIDS_MIN_RATIO);
	details.androidsMaxRatio = reader.getULong(REQUEST_FORTRESS_ANDROIDS_INFORMATION_ANDROIDS_MAX_RATIO);

    readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_CLOAKING, details.cloaking);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_DEFLECTORSHIELDS, details.deflectorShields);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_ENERGETICSYSTEM, details.energeticSystem);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_MAINFRAMESYSTEM, details.mainframeSystem);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_MECHANICS, details.mechanics);	
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_MININGDEVICES, details.miningDevices);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_OTHEREQUIPMENT, details.otherEquipment);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_PROBEDEVICES,  details.probeDevices);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_SENSORS, details.sensors);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_TRANSPORTBEAM, details.transportBeam);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_WAREHOUSE, details.warehouse);
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_WEAPONS, details.weapons);	
	readAndroidsAssignment(reader, REQUEST_ANDROIDS_ASSIGNMENT_SECTION_STRUCTURALINTEGRITY, details.structuralIntegrity);
}

void CommandClient::readAndroidsAssignment(ValueReader& reader, const std::string & section, androids_assignment & assignment) {
    std :: stringstream ss;

	ss << section << REQUEST_ANDROIDS_ASSSIGNMENT_PRIORITY;
	assignment.priority = reader.getULong(ss.str());
    ss.str("");

	ss << section << REQUEST_ANDROIDS_ASSSIGNMENT_RATIO;
	assignment.ratio = reader.getULong(ss.str());
    ss.str("");
}

void CommandClient::processUpdateShipAndroidsInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_SHIP_ANDROIDS_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_SHIP_ANDROIDS_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateShipAndroidsInformationFAIL(fortressId, fail);
}

void CommandClient::processUpdateBaseAndroidsInformationFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_BASE_ANDROIDS_INFORMATION_FORTRESSID);
	std::string fail = reader.getString(REQUEST_BASE_ANDROIDS_INFORMATION_ANSWER_FAIL);

	mainWindow_->answerUpdateBaseAndroidsInformationFAIL(fortressId, fail);
}

void CommandClient::changeShipAndroidsState(id_t fortressId, ship_androids_request_status & state) {
	socketClient_->sendAndFreeMessage(requestWriter::change_ship_androids_state(fortressId, state));
}

void CommandClient::changeBaseAndroidsState(id_t fortressId, base_androids_request_status & state) {
	socketClient_->sendAndFreeMessage(requestWriter::change_base_androids_state(fortressId, state));
}

void CommandClient::processChangeShipAndroidsState(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processChangeShipAndroidsStateFAIL(reader);
	}
}

void CommandClient::processChangeBaseAndroidsState(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		processChangeBaseAndroidsStateFAIL(reader);
	}
}

void CommandClient::processChangeShipAndroidsStateFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_CHANGE_SHIP_ANDROIDS_STATE_ANSWER_FORTRESSID);
	std::string fail = reader.getString(REQUEST_CHANGE_SHIP_ANDROIDS_STATE_ANSWER_FAIL);

	mainWindow_->answerChangeShipAndroidsStateFAIL(fortressId, fail);
}

void CommandClient::processChangeBaseAndroidsStateFAIL(ValueReader & reader) {
	id_t fortressId = reader.getId(REQUEST_CHANGE_BASE_ANDROIDS_STATE_ANSWER_FORTRESSID);
	std::string fail = reader.getString(REQUEST_CHANGE_BASE_ANDROIDS_STATE_ANSWER_FAIL);

	mainWindow_->answerChangeBaseAndroidsStateFAIL(fortressId, fail);
}

void CommandClient::processPing(message * protocolMessage) {
	lastPingAcknowledgementTime_ = clock();
}

void CommandClient::connectToServer(const std::string & server, unsigned long port) {
	currentLoginInformation_.server = server;
	currentLoginInformation_.port = port;
	currentLoginInformation_.name = "";
	currentLoginInformation_.password = "";

	socketClient_->connectToServer(server, port);
}

void CommandClient::disconnectFromServer() {
	socketClient_->disconnectFromServer();
}

void CommandClient::reconnect() {
	login(currentLoginInformation_);
}

LoginDetails CommandClient::getCurrentLogin() {
	return currentLoginInformation_;
}

void CommandClient::processUpdateBaseHangarItemInformation(message * protocolMessage) {
	
	ValueReader reader(protocolMessage);

	hangar_item_status status;

	status.patternName = reader.getString(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_PATTERN_NAME);
	status.constructionDeuterium = reader.getULongLong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_DEUTERIUM);
	status.constructionHeavyWater = reader.getULongLong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_HEAVY_WATER);
	status.constructionTitanium = reader.getULongLong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_TITANIUM);
	status.constructionUlrei = reader.getULongLong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_ULREI);
	status.isStackable = reader.getBool(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_STACKABLE);
	status.itemName = reader.getString(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_ITEM_NAME);
	status.minWeight = reader.getULong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_MIN_WEIGHT);
	status.maxWeight = reader.getULong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_MAX_WEIGHT);

	status.minSize = reader.getDouble(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_MIN_SIZE);
	status.maxSize = reader.getDouble(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_MAX_SIZE);
	status.minRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_MIN_ANDROIDS);
	status.maxRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGAR_ITEM_INFORMATION_ANSWER_HANGAR_ITEM_MAX_ANDROIDS);
	
	mainWindow_->answerUpdateBaseHangarItemInformation(status);
}

void CommandClient::processUpdateBaseHangarsInformation(message * protocolMessage) {
	
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {

		id_t fortressId = reader.getId(REQUEST_BASE_HANGARS_INFORMATION_FORTRESSID);
		std::string reason = reader.getString(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_FAIL);

		mainWindow_->answerUpdateBaseHangarsInformationFAIL(fortressId, reason);

		return;
	}

	hangars_status status;

	id_t fortressId = reader.getId(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_FORTRESS_ID);
	status.selectedHangarId = reader.getId(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_HANGAR_ID);

	status.isHangarFree = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_FREE);
	status.isShipInDock = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SHIP_IN_DOCK);

	status.isItemUnderConstruction = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_ITEM_UNDER_CONSTRUCTION);
	status.isShipUnderConstruction = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SHIP_UNDER_CONSTRUCTION);
	status.isWhateverUnderConstruction = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_WHATEVER_UNDER_CONSTRUCTION);

	status.damageStatus = reader.getDouble(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_DAMAGE_STATUS);

	status.actualConstructedPoints = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_ACTUAL_POINTS);
	status.targetConstructedPoints = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_TARGET_POINTS);
	status.constructionGradient = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTION_GRADIENT);

	status.constructedItem.patternName = reader.getString(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_PATTERN_NAME);
	status.constructedItem.constructionDeuterium = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_DEUTERIUM);
	status.constructedItem.constructionHeavyWater = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_HEAVY_WATER);
	status.constructedItem.constructionTitanium = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_TITANIUM);
	status.constructedItem.constructionUlrei = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ULREI);
	status.constructedItem.itemName = reader.getString(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_NAME);
	status.constructedItem.constructionTime = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_CONSTRUCTION_TIME);
	status.constructedItem.count = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_COUNT);
	status.constructedItem.isStackable = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_STACKABLE);

	status.constructedItem.actSize = reader.getDouble(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_ACT_SIZE);
	status.constructedItem.minSize = reader.getDouble(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_MIN_SIZE);
	status.constructedItem.maxSize = reader.getDouble(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_MAX_SIZE);
	status.constructedItem.actRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_ACT_ANDROIDS);
	status.constructedItem.minRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_MIN_ANDROIDS);
	status.constructedItem.maxRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_CONSTRUCTED_ITEM_MAX_ANDROIDS);

	status.selectedItem.patternName = reader.getString(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_PATTERN_NAME);
	
	// Read selected item data only if it is different from constructed item
	if (status.selectedItem.patternName != status.constructedItem.patternName) {	
		status.selectedItem.constructionDeuterium = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_DEUTERIUM);
		status.selectedItem.constructionHeavyWater = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_HEAVY_WATER);
		status.selectedItem.constructionTitanium = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_TITANIUM);
		status.selectedItem.constructionUlrei = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ULREI);
		status.selectedItem.itemName = reader.getString(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_NAME);
		status.selectedItem.minWeight = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_MIN_WEIGHT);
		status.selectedItem.maxWeight = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_MAX_WEIGHT);
		status.selectedItem.isStackable = reader.getBool(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_STACKABLE);

		status.selectedItem.minSize = reader.getDouble(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_MIN_SIZE);
		status.selectedItem.maxSize = reader.getDouble(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_MAX_SIZE);
		status.selectedItem.minRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_MIN_ANDROIDS);
		status.selectedItem.maxRequiredAndroidCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_SELECTED_ITEM_MAX_ANDROIDS);
	}

	status.actualLevel = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_LEVEL);

	size_t hangarCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_HANGAR_COUNT);

	for (int index = 1; index < hangarCount + 1; ++index) {
		status.hangarIds.push_back(reader.getId(create_param_name(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_HANGAR_HANGAR_ID, index)));
	}

	size_t shipClassesCount = reader.getULongLong(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_FORTRESS_CLASS_COUNT);

	for (int index = 1; index < shipClassesCount + 1; ++index) {
		fortress_class_simple_data classData;

		classData.id = reader.getId(create_param_name(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_FORTRESS_CLASS_ID, index));
		classData.name = reader.getString(create_param_name(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_FORTRESS_CLASS_NAME, index));
		classData.quality = reader.getDouble(create_param_name(REQUEST_BASE_HANGARS_INFORMATION_ANSWER_FORTRESS_CLASS_QUALITY, index));

		status.availableShipClasses.push_back(classData);
	}		

	mainWindow_->answerUpdateBaseHangarsInformation(status);
}

void CommandClient::updateBaseHangarsInformation(id_t fortressId, id_t hangarId, const std::string & patternName) {
	socketClient_->sendAndFreeMessage(requestWriter::base_hangar_information(fortressId, hangarId, patternName));
}

void CommandClient::updateBaseHangarsInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::base_hangar_information(fortressId, 0, ""));
}

void CommandClient::updateBaseHangarItemInformation(const std::string & patternName) {
	socketClient_->sendAndFreeMessage(requestWriter::base_hangar_item_information(patternName));
}

void CommandClient::hangarBuildItem(id_t fortressId, const HangarServerInputData & data) {
	socketClient_->sendAndFreeMessage(requestWriter::base_hangar_build_item(fortressId, data));
}

void CommandClient::hangarCancelItem(id_t fortressId, id_t hangarId) {
	socketClient_->sendAndFreeMessage(requestWriter::base_hangar_cancel_item(fortressId, hangarId));
}

void CommandClient::processUnmountFortressDevice(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_FORTRESSID);
		std::string patternName = reader.getString(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_PATTERN_NAME);
		return mainWindow_->answerUnmountFortressDeviceFAIL(fortressId, patternName);
	}

	unmount_device_info unmountData;

	unmountData.working = reader.getULongLong(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_WORKING);
	unmountData.damaged = reader.getULongLong(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_DAMAGED);
	unmountData.fortressId = reader.getId(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_FORTRESSID);
	std::string mountingResult = reader.getString(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_MOUNTING_RESULT);    
	unmountData.patternName = reader.getString(REQUEST_UNMOUNT_FORTRESS_DEVICE_ANSWER_PATTERN_NAME);   

	mainWindow_->answerUnmountFortressDevice(unmountData, mountingResult);
}

void CommandClient::unmountFortressDevice(const unmount_device_info & data) {
	socketClient_->sendAndFreeMessage(requestWriter::unmount_fortress_device(data));
}

void CommandClient::sendTradeInvitation(id_t hostFortressId, id_t invitedFortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::send_trade_invitation(hostFortressId, invitedFortressId));
}

void CommandClient::cancelTrade() {
	socketClient_->sendAndFreeMessage(requestWriter::cancel_trade_with_partner());
}

void CommandClient::processSendTradeInvitation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {

	}

    string reason = reader.getString(REQUEST_SEND_TRADE_INVITATION_ANSWER_REASON);
	string tradeRole = reader.getString(REQUEST_SEND_TRADE_INVITATION_ANSWER_TRADE_ROLE); 

	trade_invitation_data invitation;
	readInvitation(reader, invitation);

	if (tradeRole == PROTOCOL_TRADE_ROLE_SELF_TRADER || tradeRole == PROTOCOL_TRADE_ROLE_LOOT_TRADER) {
		trade_data selfTradeData;
		readTradeData(reader, REQUEST_SEND_TRADE_INVITATION_SELF_DATA_PREFIX, selfTradeData);

		trade_data partnerTradeData;
		readTradeData(reader, REQUEST_SEND_TRADE_INVITATION_PARTNER_DATA_PREFIX, partnerTradeData);

		mainWindow_->answerSendTradeInvitation(invitation, selfTradeData, partnerTradeData, reason, tradeRole);
	}
	else if (tradeRole == PROTOCOL_TRADE_ROLE_SPACE_TRADER) {
		trade_data selfTradeData;
		readTradeData(reader, REQUEST_SEND_TRADE_INVITATION_SELF_DATA_PREFIX, selfTradeData);

		mainWindow_->answerSendTradeInvitation(invitation, selfTradeData, reason, tradeRole);
	}
	else {
		mainWindow_->answerSendTradeInvitation(invitation, reason, tradeRole);
	}
}

void CommandClient::processSendTradeInvitationFAIL(ValueReader & reader)  {

}

void CommandClient::tradePartnerFortresses(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::trade_partner_fortresses(fortressId));
}

void CommandClient::processTradePartnerFortresses(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_REASON);
		mainWindow_->answerTradePartnerFortressesFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_FORTRESS_ID);

	std::vector<SimpleItem> ownedFortresses;

	unsigned long ownedFortressesCount = reader.getULong(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_OWNED_FORTRESS_COUNT);

	for (int i = 1; i < ownedFortressesCount + 1; ++i) {
		SimpleItem item;

		item.id  = reader.getId(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_OWNED_FORTRESS_ID, i));
		item.name = reader.getString(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_OWNED_FORTRESS_NAME, i));
		item.fortressType = (EFortressType) reader.getULong(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_OWNED_FORTRESS_TYPE, i));
		item.isShell = reader.getBool(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_OWNED_FORTRESS_SHELL, i));

		ownedFortresses.push_back(item);
	}

	std::vector<SimpleItem> notOwnedFortresses;

	unsigned long notOwnedFortressesCount = reader.getULong(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_NOT_OWNED_FORTRESS_COUNT);

	for (int i = 1; i < notOwnedFortressesCount + 1; ++i) {
		SimpleItem item;

		item.id  = reader.getId(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_NOT_OWNED_FORTRESS_ID, i));
		item.name = reader.getString(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_NOT_OWNED_FORTRESS_NAME, i));
		item.realmName = reader.getString(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_NOT_OWNED_FORTRESS_REALM_NAME, i));
		item.fortressType = (EFortressType) reader.getULong(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_NOT_OWNED_FORTRESS_TYPE, i));
		item.isShell = reader.getBool(create_param_name(REQUEST_TRADE_PARTNER_FORTRESSES_ANSWER_NOT_OWNED_FORTRESS_SHELL, i));

		notOwnedFortresses.push_back(item);
	}

	mainWindow_->answerTradePartnerFortresses(fortressId, ownedFortresses, notOwnedFortresses);
}

void CommandClient::processReceiveTradeInvitation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	trade_invitation_data invitation;
	readInvitation(reader, invitation);

	mainWindow_->receiveTradeInvitation(invitation);
}

void CommandClient::decideTradeInvitation(id_t ownedFortressId, id_t partnerFortressId, bool acceptInvitation) {
	socketClient_->sendAndFreeMessage(requestWriter::decide_trade_invitation(ownedFortressId, partnerFortressId, acceptInvitation));
}

void CommandClient::cancelTradeCommit(id_t selfFortressId, id_t partnerFortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::cancel_trade_commit(selfFortressId, partnerFortressId));
}

void CommandClient::processCancelTradeCommit(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	std::string reason = reader.getString(REQUEST_CANCEL_TRADE_COMMIT_ANSWER_REASON);
	id_t selfFortressId = reader.getId(REQUEST_CANCEL_TRADE_COMMIT_ANSWER_SELF_FORTRESS_ID);
	id_t partnerFortressId = reader.getId(REQUEST_CANCEL_TRADE_COMMIT_ANSWER_PARTNER_FORTRESS_ID);

	mainWindow_->answerCancelTradeCommit(selfFortressId, partnerFortressId, reason);
}



void CommandClient::processDecideTradeInvitation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	bool accepted = reader.getBool(REQUEST_DECIDE_TRADE_INVITATION_ANSWER_ACCEPTED);

	trade_invitation_data invitation;
	readInvitation(reader, invitation);

	if (accepted) {
		trade_data tradeData;
		readTradeData(reader, REQUEST_DECIDE_TRADE_INVITATION_ANSWER_SELF_DATA_PREFIX, tradeData);
		mainWindow_->answerDecideTradeInvitation(invitation, tradeData);
	}
	else {
		mainWindow_->answerDecideTradeInvitation(invitation);
	}
}

void CommandClient::processReceiveTradeInvitationDecision(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	bool accepted = reader.getBool(RECEIVE_TRADE_INVITATION_DECISION_ACCEPTED);

	trade_invitation_data invitation;
	readInvitation(reader, invitation);

	if (accepted) {
		trade_data tradeData;
		readTradeData(reader, RECEIVE_TRADE_INVITATION_DECISION_ANSWER_SELF_DATA_PREFIX, tradeData);
		mainWindow_->receiveTradeInvitationDecision(invitation, tradeData);
	}
	else {
		mainWindow_->receiveTradeInvitationDecision(invitation);
	}	
}

void CommandClient::readInvitation(ValueReader & reader, trade_invitation_data & invitation) {
	invitation.hostFortressId = reader.getId(TRADE_INVITATION_HOST_FORTRESS_ID);
	invitation.hostFortressName = reader.getString(TRADE_INVITATION_HOST_FORTRESS_NAME);
	invitation.hostId = reader.getId(TRADE_INVITATION_HOST_ID);
	invitation.hostName = reader.getString(TRADE_INVITATION_HOST_NAME);
	invitation.invitedFortressId = reader.getId(TRADE_INVITATION_INVITED_FORTRESS_ID);
	invitation.invitedFortressName = reader.getString(TRADE_INVITATION_INVITED_FORTRESS_NAME);
	invitation.invitedId = reader.getId(TRADE_INVITATION_INVITED_ID);
	invitation.invitedName = reader.getString(TRADE_INVITATION_INVITED_NAME);

	invitation.hostIsShip = reader.getBool(TRADE_INVITATION_HOST_IS_SHIP);
	invitation.invitedIsShip = reader.getBool(TRADE_INVITATION_INVITED_IS_SHIP);
}

void CommandClient::processCancelTrade(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	std::string reason = reader.getString(REQUEST_CANCEL_TRADE_ANSWER_REASON);
	std::string tradeRole = reader.getString(REQUEST_CANCEL_TRADE_ANSWER_TRADE_ROLE);
	id_t ownedFortressId = reader.getId(REQUEST_CANCEL_TRADE_ANSWER_OWNED_FORTRESS_ID);
	id_t partnerFortressId = reader.getId(REQUEST_CANCEL_TRADE_ANSWER_PARTNER_FORTRESS_ID);

	mainWindow_->answerCancelTrade(ownedFortressId, partnerFortressId, reason, tradeRole);
}

void CommandClient::processReceiveTradeCancelation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	id_t ownedFortressId = reader.getId(RECEIVE_TRADE_CANCELATION_OWNED_FORTRESS_ID);
	id_t partnerFortressId = reader.getId(RECEIVE_TRADE_CANCELATION_PARTNER_FORTRESS_ID);

	mainWindow_->receiveTradeCancelation(ownedFortressId, partnerFortressId);
}

void CommandClient::readTradeData(ValueReader & reader, const std::string & prefix, trade_data & tradeData) {

	readWarehouseItemsList(reader, prefix, tradeData.tradeItems);

	tradeData.deuterium = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_DEUTERIUM));
	tradeData.heavyWater = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_HEAVY_WATER));
	tradeData.ilmenite = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_ILMENITE));
	tradeData.quarkGluonPlasma = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_QUARK_GLUON_PLASMA));
	tradeData.titanium = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_TITANIUM));
	tradeData.ulrea = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_ULREA));
	tradeData.zirconiumCrystal = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_ZIRCONIUM_CRYSTAL));
	tradeData.energy = reader.getULongLong(create_param_name(prefix, TRADE_ITEM_DATA_ENERGY));
}

void CommandClient::processMoveTradeItem(message * protocolMessage) {
	ValueReader reader(protocolMessage);	

	trade_movement_data tradeData;
	readTradeMovementData(reader, tradeData);

	if (!reader.isAnswerOk()) {
		std::string reason = reader.getString(REQUEST_MOVE_TRADE_ITEM_ANSWER_FAIL_REASON);
		mainWindow_->answerMoveTradeItemFAIL(tradeData, reason);
		return;
	}

	bool isAuthor = reader.getBool(REQUEST_MOVE_TRADE_ITEM_ANSWER_AUTHOR);
	mainWindow_->answerMoveTradeItem(tradeData, isAuthor);
}

void CommandClient::readTradeMovementData(ValueReader & reader, trade_movement_data & tradeData) {
	tradeData.selfFortressId = reader.getId(TRADE_MOVEMENT_DATA_SELF_FORTRESS_ID);
	tradeData.partnerFortressId = reader.getId(TRADE_MOVEMENT_DATA_PARTNER_FORTRESS_ID);
	tradeData.tradeDirection = reader.getString(TRADE_MOVEMENT_DATA_TRADE_DIRECTION);
	
	readWarehouseItem(reader, TRADE_MOVEMENT_DATA_PREFIX, 0, tradeData.item);
}

void CommandClient::moveTradeItem(const trade_client_movement_data & tradeData) {
	socketClient_->sendAndFreeMessage(requestWriter::move_trade_item(tradeData));
}

void CommandClient::processCommitTrade(message * protocolMessage)
{
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		return;
	}

	ETradingResult result = reader.getTradingResult(REQUEST_COMMIT_TRADE_ANSWER_RESULT);
	id_t selfFortressId = reader.getId(REQUEST_COMMIT_TRADE_ANSWER_SELF_FORTRESS_ID);
	id_t partnerFortressId = reader.getId(REQUEST_COMMIT_TRADE_ANSWER_PARTNER_FORTRESS_ID);

	mainWindow_->answerCommitTrade(selfFortressId, partnerFortressId, result);
}

void CommandClient::processPrepareCommitTrade(message * protocolMessage)
{
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		return;
	}
	
	ETradingCommitRole commitRole = reader.getTradingCommitRole(REQUEST_PREPARE_COMMIT_TRADE_ANSWER_TRADE_COMMIT_ROLE);
	id_t selfFortressId = reader.getId(REQUEST_COMMIT_TRADE_ANSWER_SELF_FORTRESS_ID);
	id_t partnerFortressId = reader.getId(REQUEST_COMMIT_TRADE_ANSWER_PARTNER_FORTRESS_ID);

	mainWindow_->answerPrepareCommitTrade(selfFortressId, partnerFortressId, commitRole);
}

void CommandClient::commitTrade(id_t selfFortressId, id_t partnerFortressId, const client_trade_data & selfOffer, const client_trade_data & partnerOffer) {
	socketClient_->sendAndFreeMessage(requestWriter::commit_trade(selfFortressId, partnerFortressId, selfOffer, partnerOffer));
}

void CommandClient::moveTradeResource(const trade_resource_movement_data & data) {
	socketClient_->sendAndFreeMessage(requestWriter::move_trade_resource(data));
}

void CommandClient::processMoveTradeResource(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	trade_resource_movement_data tradeData;
	readTradeResourceMovementData(reader, tradeData);

	if (!reader.isAnswerOk()) {
		std::string reason = reader.getString(REQUEST_MOVE_TRADE_RESOURCE_ANSWER_FAIL_REASON);
		mainWindow_->answerMoveTradeResourceFAIL(tradeData, reason);
		return;
	}

	bool isAuthor = reader.getBool(REQUEST_MOVE_TRADE_RESOURCE_ANSWER_AUTHOR);

	mainWindow_->answerMoveTradeResource(tradeData, isAuthor);
}

void CommandClient::readTradeResourceMovementData(ValueReader & reader, trade_resource_movement_data & tradeData) {
	tradeData.selfFortressId = reader.getId(TRADE_RESOURCE_MOVEMENT_DATA_SELF_FORTRESS_ID);
	tradeData.partnerFortressId = reader.getId(TRADE_RESOURCE_MOVEMENT_DATA_PARTNER_FORTRESS_ID);
	tradeData.count = reader.getULongLong(TRADE_RESOURCE_MOVEMENT_DATA_COUNT);
	tradeData.tradeDirection = reader.getString(TRADE_RESOURCE_MOVEMENT_DATA_TRADE_DIRECTION);
	tradeData.resourceType = reader.getGameResourceType(TRADE_RESOURCE_MOVEMENT_DATA_RESOURCE_TYPE);
}

void CommandClient::getPlayerDiscoveredStars(void)
{
	socketClient_->sendAndFreeMessage(requestWriter::discoveredStarsRequest());
}
void CommandClient::processPlayerDiscoveredStars( message * protocolMessage ) 
{
	discovered_stars discoveredStars;

	ValueReader reader(protocolMessage);
	unsigned long starCount = reader.getULong( create_count_name(REQUEST_DISCOVERED_STARS_LIST_PREFIX) );

	for ( int i=1; i< starCount+1; ++i)
	{
		discovered_star star;
		star.name = reader.getString( create_param_name(REQUEST_DISCOVERED_STARS_LIST_PREFIX, REQUEST_DISCOVERED_STAR_ANSWER_DISCOVERED_STAR_NAME, i) );
		star.id =  reader.getULong( create_param_name(REQUEST_DISCOVERED_STARS_LIST_PREFIX, REQUEST_DISCOVERED_STAR_ANSWER_DISCOVERED_STAR_ID, i));
		star.pos.x = reader.getDouble(create_param_name(REQUEST_DISCOVERED_STARS_LIST_PREFIX, REQUEST_DISCOVERED_STAR_ANSWER_DISCOVERED_STAR_POS_X, i));
		star.pos.y = reader.getDouble(create_param_name(REQUEST_DISCOVERED_STARS_LIST_PREFIX, REQUEST_DISCOVERED_STAR_ANSWER_DISCOVERED_STAR_POS_Y, i));
	
		discoveredStars.dsc_stars.push_back( star);
	}
	
	mainWindow_->answerPlayerExploredStars( discoveredStars );	
}

void CommandClient::processMountFortressDevice(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_MOUNT_FORTRESS_DEVICE_ANSWER_FORTRESSID);
		std::string reason = reader.getString(REQUEST_MOUNT_FORTRESS_DEVICE_ANSWER_FAIL);    
		id_t itemId = reader.getId(REQUEST_MOUNT_FORTRESS_DEVICE_ANSWER_ITEM_ID);   

		mainWindow_->answerMountFortressDeviceFAIL(fortressId, itemId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_MOUNT_FORTRESS_DEVICE_ANSWER_FORTRESSID);
	std::string mountingResult = reader.getString(REQUEST_MOUNT_FORTRESS_DEVICE_ANSWER_MOUNTING_RESULT);    
	id_t itemId = reader.getId(REQUEST_MOUNT_FORTRESS_DEVICE_ANSWER_ITEM_ID);   

	mainWindow_->answerMountFortressDevice(fortressId, itemId, mountingResult);
}

void CommandClient::mountFortressDevice(const mount_device_info & data) {
	socketClient_->sendAndFreeMessage(requestWriter::mount_fortress_device(data));
}

void CommandClient::fortressInWeaponsRange(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortresses_in_weapons_range(fortressId));
}

void CommandClient::fortressesInConquerRange(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortresses_in_conquer_range(fortressId));
}

void CommandClient::processFortressesInWeaponsRange(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	id_t fortressId = reader.getId(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_FORTRESS_ID);

	std::vector<SimpleItem> ships;

	unsigned long shipCount = reader.getULong(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_SHIP_COUNT);

	for (int index = 1; index < shipCount + 1; ++index) {
		SimpleItem shipData;

		shipData.id = reader.getId(create_param_name(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_SHIP_ID, index));
		shipData.name = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_SHIP_NAME, index));
		shipData.realmName = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_SHIP_REALM_NAME, index));

		ships.push_back(shipData);
	}

	std::vector<SimpleItem> bases;

	unsigned long baseCount = reader.getULong(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_BASE_COUNT);

	for (int index = 1; index < baseCount + 1; ++index) {
		SimpleItem baseData;

		baseData.id = reader.getId(create_param_name(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_BASE_ID, index));
		baseData.name = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_BASE_NAME, index));
		baseData.realmName = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_BASE_REALM_NAME, index));

		bases.push_back(baseData);
	}

	fortress_attack_information data;

	readFortressFightData(reader, data.fortressFightData, 1);

	data.fortressInWeaponsTargetId = reader.getId(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_FORTRESS_IN_WEAPONS_TARGET_ID);

	if (data.fortressInWeaponsTargetId != 0) {
		data.fortressInWeaponsTargetName = reader.getString(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_FORTRESS_IN_WEAPONS_TARGET_NAME);
		data.fortressInWeaponsRangeTargetRealmName = reader.getString(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_FORTRESS_IN_WEAPONS_TARGET_REALM_NAME);		
		data.fortressInWeaponsRangeTargetType = reader.getULong(REQUEST_FORTRESSES_IN_WEAPONS_RANGE_ANSWER_FORTRESS_IN_WEAPONS_TARGET_TYPE);		
	}

	mainWindow_->answerFortressesInRange(data, ships, bases);
}

void CommandClient::attackFortress(id_t selfFortressId, id_t enemyFortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::attack_fortress(selfFortressId, enemyFortressId));
}

void CommandClient::stopAttackFortress(id_t selfFortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::stop_attack_fortress(selfFortressId));
}

void CommandClient::processAttackFortress(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	id_t selfFortressId = reader.getId(REQUEST_ATTACK_FORTRESS_ANSWER_SELF_FORTRESS_ID);
	id_t enemyFortressId = reader.getId(REQUEST_ATTACK_FORTRESS_ANSWER_SELF_FORTRESS_ID);

	if (!reader.isAnswerOk()) {
		std::string reason = reader.getString(REQUEST_ATTACK_FORTRESS_ANSWER_FAIL);

		mainWindow_->answerAttackFortressFAIL(selfFortressId, enemyFortressId, reason);
	}
	else {	
		mainWindow_->answerAttackFortress(selfFortressId, enemyFortressId);
	}
}

void CommandClient::processStopAttackFortress(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	id_t selfFortressId = reader.getId(REQUEST_ATTACK_FORTRESS_ANSWER_SELF_FORTRESS_ID);

	if (!reader.isAnswerOk()) {
		std::string reason = reader.getString(REQUEST_ATTACK_FORTRESS_ANSWER_FAIL);

		mainWindow_->answerStopAttackFortressFAIL(selfFortressId, reason);
	}
	else {	
		mainWindow_->answerStopAttackFortress(selfFortressId);
	}
}

void CommandClient::processFightActionReport(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	fight_action_report report;

	report.selfFortressId = reader.getId(REQUEST_FIGHT_ACTION_REPORT_SELF_FORTRESS_ID);
	report.selfFortressName = reader.getString(REQUEST_FIGHT_ACTION_REPORT_SELF_FORTRESS_NAME);
	report.selfRealmName = reader.getString(REQUEST_FIGHT_ACTION_REPORT_SELF_FORTRESS_REALM_NAME);
	report.selfIsShip = reader.getBool(REQUEST_FIGHT_ACTION_REPORT_SELF_SHIP);

	report.enemyFortressExists = reader.getBool(REQUEST_FIGHT_ACTION_REPORT_ENEMY_FORTRESS_EXISTS);

	if (report.enemyFortressExists) {
		report.enemyFortressId = reader.getId(REQUEST_FIGHT_ACTION_REPORT_ENEMY_FORTRESS_ID);
		report.enemyFortressName = reader.getString(REQUEST_FIGHT_ACTION_REPORT_ENEMY_FORTRESS_NAME);
		report.enemyRealmName = reader.getString(REQUEST_FIGHT_ACTION_REPORT_ENEMY_FORTRESS_REALM_NAME);
		report.enemyIsShip = reader.getBool(REQUEST_FIGHT_ACTION_REPORT_ENEMY_SHIP);
	}

	if (!string_to_fight_action_type(reader.getString(REQUEST_FIGHT_ACTION_REPORT_ACTION), report.action)) {
		KODIAK_DEBUG_COUT << "Unknown fight action type in method void CommandClient::processFightActionReport(message * protocolMessage)";
		return;
	}	

	mainWindow_->answerFightActionReport(report);
}

void CommandClient::processNavigationPlanets(message * protocolMessage) {

	ValueReader reader(protocolMessage);

	if (protocolMessage->getAnswerKind() == AK_FAIL) {
		processPlanetsInStarAreaFAIL(reader);
	}
	else {
		unsigned long planetCount = reader.getULong(REQUEST_NAVIGATION_PLANETS_ANSWER_COUNT);

		NavigationPlanetsInStarAreaDetails planetsInArea;
		
		planetsInArea.shipId = reader.getId(REQUEST_NAVIGATION_PLANETS_SHIPID);
		planetsInArea.areaId = reader.getId(REQUEST_NAVIGATION_PLANETS_AREAID);
        planetsInArea.sunObjectRadius = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_SUN_OBJ_RADIUS);
        planetsInArea.sunAreaRadius = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_SUN_ARE_RADIUS);
        planetsInArea.sunName = reader.getString(REQUEST_NAVIGATION_PLANETS_ANSWER_SUN_NAME);
        planetsInArea.sunWeight = reader.getWeight(REQUEST_NAVIGATION_PLANETS_ANSWER_SUN_WEIGHT);
        planetsInArea.sunType = reader.getULong(REQUEST_NAVIGATION_PLANETS_ANSWER_SUN_TYPE);
		
		for (int counter = 1; counter < planetCount + 1; ++counter) {
			NavigationPlanetDetails planetDetails;
			readPlanetDetails(reader, counter, planetDetails);

			planetDetails.heavyWaterModifier = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_HW_MODIFIER, counter);
			planetDetails.crystalsModifier = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_ZI_MODIFIER, counter);
			planetDetails.ilmeniteModifier = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_IL_MODIFIER, counter);
			planetDetails.planetType = (SpaceObjectPlanetType) reader.getULong(REQUEST_NAVIGATION_PLANETS_ANSWER_TYPE, counter);

			planetsInArea.planets.push_back(planetDetails);
		}

		mainWindow_->answerNavigationPlanets(planetsInArea);
	}
}

void CommandClient::readPlanetDetails(const ValueReader & reader, int index, NavigationPlanetDetails & details) {	
	details.id = reader.getId(REQUEST_NAVIGATION_PLANETS_ANSWER_PLANETID, index);
	details.pivotX = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_PIVOTX, index);
	details.pivotY = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_PIVOTY, index);
	details.speed = reader.getSpeed(REQUEST_NAVIGATION_PLANETS_ANSWER_SPEED, index);
	details.radius = reader.getDistance(REQUEST_NAVIGATION_PLANETS_ANSWER_RADIUS, index);
	details.size = reader.getDistance(REQUEST_NAVIGATION_PLANETS_ANSWER_SIZE, index);
	details.angle = reader.getDistance(REQUEST_NAVIGATION_PLANETS_ANSWER_ANGLE, index);
	details.weight = reader.getWeight(REQUEST_NAVIGATION_PLANETS_ANSWER_WEIGHT, index);
	details.yearPeriod = reader.getULongLong(REQUEST_NAVIGATION_PLANETS_ANSWER_YEARP, index);
	details.dayPeriod = reader.getULongLong(REQUEST_NAVIGATION_PLANETS_ANSWER_DAYP, index);
	details.type = (PlanetType) reader.getULong(REQUEST_NAVIGATION_PLANETS_ANSWER_TYPE, index);
	details.dayTemperature = reader.getLong(REQUEST_NAVIGATION_PLANETS_ANSWER_DAYTEMP, index);
	details.nightTemperature = reader.getLong(REQUEST_NAVIGATION_PLANETS_ANSWER_NIGHTTEMP, index);
	details.sea = reader.getLong(REQUEST_NAVIGATION_PLANETS_ANSWER_SEA, index);
	details.heavyWaterSource = reader.getLong(REQUEST_NAVIGATION_PLANETS_ANSWER_HWSO, index);
	details.crystalsSource = reader.getLong(REQUEST_NAVIGATION_PLANETS_ANSWER_ZISO, index);
	details.ilmeniteSource = reader.getLong(REQUEST_NAVIGATION_PLANETS_ANSWER_ILSO, index);    
	details.name = reader.getString(REQUEST_NAVIGATION_PLANETS_ANSWER_NAME, index);	
	details.shipDistance = reader.getDouble(REQUEST_NAVIGATION_PLANETS_ANSWER_DISTSHP, index);
}

void CommandClient::processUncontrollableFortresses(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_FAIL);
		mainWindow_->answerUncontrollableFortressesFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_FORTRESS_ID);

	std::vector<FortressInRangeData> ships;

	unsigned long shipCount = reader.getULong(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_SHIP_COUNT);

	for (int i = 1; i < shipCount + 1; ++i) {
		FortressInRangeData item;

		item.id  = reader.getId(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_SHIP_ID, i));
		item.name = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_SHIP_NAME, i));
		item.isInTradeRange = reader.getBool(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_SHIP_IN_TRADE_RANGE, i));
		item.isInConquerRange = reader.getBool(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_SHIP_IN_CONQUER_RANGE, i));
		item.isShell = reader.getBool(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_SHIP_IN_IS_SHELL, i));

		ships.push_back(item);
	}

	std::vector<FortressInRangeData> bases;

	unsigned long baseCount = reader.getULong(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_COUNT);

	for (int i = 1; i < baseCount + 1; ++i) {
		FortressInRangeData item;

		item.id  = reader.getId(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_ID, i));
		item.name = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_NAME, i));
		item.realmName = reader.getString(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_REALM_NAME, i));
		item.isInTradeRange = reader.getBool(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_IN_TRADE_RANGE, i));
		item.isInConquerRange = reader.getBool(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_IN_CONQUER_RANGE, i));
		item.isShell = reader.getBool(create_param_name(REQUEST_FORTRESSES_IN_CONQUER_RANGE_ANSWER_BASE_IN_IS_SHELL, i));

		bases.push_back(item);
	}

	mainWindow_->answerUncontrollableFortresses(fortressId, ships, bases);
}

void CommandClient::processBuildNewBaseShell(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_BUILD_NEW_BASE_SHELL_ANSWER_SELF_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_BUILD_NEW_BASE_SHELL_ANSWER_FAIL);
		mainWindow_->answerBuildNewBaseShellFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_BUILD_NEW_BASE_SHELL_ANSWER_SELF_FORTRESS_ID);
	BaseBuildingResult result = (BaseBuildingResult) reader.getULong(REQUEST_BUILD_NEW_BASE_SHELL_ANSWER_BUILDING_RESULT);
	unsigned long long newTitan = reader.getULong(REQUEST_BUILD_NEW_BASE_SHELL_ANSWER_NEW_TITAN);

	mainWindow_->answerBuildNewBaseShell(fortressId, result, newTitan);
}

void CommandClient::buildNewBaseShell(id_t fortressId, id_t fortressClassId, unsigned long long buildingTitanium) {
	socketClient_->sendAndFreeMessage(requestWriter::build_new_base_shell(fortressId, fortressClassId, buildingTitanium));
}

void CommandClient::processAvailableFortressClasses(message *protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t selfFortressId = reader.getId(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_SELF_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_FAIL);
		mainWindow_->answerAvailableFortressClassesFAIL(selfFortressId, reason);
		return;
	}

	id_t selfFortressId = reader.getId(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_SELF_FORTRESS_ID);
						 
	unsigned long shipClassCount = reader.getULong(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_SHIP_CLASS_COUNT);

	std::list<fortress_class_simple_data> shipClasses;

	for (int shipIndex = 1; shipIndex < shipClassCount + 1; ++shipIndex) {
		fortress_class_simple_data data;
		data.id = reader.getId(create_param_name(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_SHIP_CLASS_ID, shipIndex));
		data.name = reader.getString(create_param_name(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_SHIP_CLASS_NAME, shipIndex));
		data.quality = reader.getDouble(create_param_name(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_SHIP_CLASS_QUALITY, shipIndex));	

		shipClasses.push_back(data);
	}

	unsigned long baseClassCount = reader.getULong(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_BASE_CLASS_COUNT);

	std::list<fortress_class_simple_data> baseClasses;

	for (int shipIndex = 1; shipIndex < baseClassCount + 1; ++shipIndex) {
		fortress_class_simple_data data;
		data.id = reader.getId(create_param_name(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_BASE_CLASS_ID, shipIndex));
		data.name = reader.getString(create_param_name(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_BASE_CLASS_NAME, shipIndex));
		data.quality = reader.getDouble(create_param_name(REQUEST_AVAILABLE_FORTRESS_CLASSES_ANSWER_BASE_CLASS_QUALITY, shipIndex));	

		baseClasses.push_back(data);
	}

	mainWindow_->answerAvailableFortressClasses(selfFortressId, shipClasses, baseClasses);
}

void CommandClient::availableFortressClasses(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::available_fortress_classes(fortressId));
}

void CommandClient::fortressClassData(id_t fortressClassId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_class_data(fortressClassId));
}

void CommandClient::processFortressClassData(message *protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressClassId = reader.getId(REQUEST_FORTRESS_CLASS_DATA_ANSWER_ID);
		std::string reason = reader.getString(REQUEST_FORTRESS_CLASS_DATA_ANSWER_FAIL);
		mainWindow_->answerFortressClassDataFAIL(fortressClassId, reason);
		return;
	}

	fortress_class_complex_data data;

	data.name = reader.getString(REQUEST_FORTRESS_CLASS_DATA_ANSWER_CLASS_NAME);
	data.id = reader.getId(REQUEST_FORTRESS_CLASS_DATA_ANSWER_ID);
	data.massRating = reader.getDouble(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MASS_RATING);
	data.maxDroneMissileLaunchers = reader.getULong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_DRONE_MISSILE_LAUNCHERS);
	data.maxHeight = reader.getDouble(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_HEIGHT);
	data.maxWidth = reader.getDouble(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_WIDTH);
	data.maxLaserGuns = reader.getULong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_LASER_GUNS);
	data.maxLength = reader.getDouble(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_LENGTH);
	data.maxTotalStructuralIntegrity = reader.getULongLong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_TOTAL_STRUCTURAL_INTEGRITY);
	data.maxWeapons = reader.getULong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_WEAPONS);
	data.minTotalStructuralIntegrity = reader.getULongLong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MIN_TOTAL_STRUCTURAL_INTEGRITY);
	data.minWeight = reader.getULongLong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MIN_WEIGHT);
	data.maxWeight = reader.getULongLong(REQUEST_FORTRESS_CLASS_DATA_ANSWER_MAX_WEIGHT);
	data.qualityRating = reader.getDouble(REQUEST_FORTRESS_CLASS_DATA_ANSWER_QUALITY_RATING);
	data.isBaseClass = reader.getBool(REQUEST_FORTRESS_CLASS_DATA_ANSWER_IS_BASE_CLASS);

	mainWindow_->answerFortressClassData(data);
}

void CommandClient::processPlayerFortressesWithBuildInformation(message * protocolMessage){
    ValueReader reader(protocolMessage);	

	std::list<fortress_build_information> ships;
	unsigned long shipCount = reader.getULong(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_COUNT);

    for (int shipIndex = 1; shipIndex < shipCount + 1; ++shipIndex) {
		fortress_build_information data;

		data.fortressId = reader.getId(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_ID, shipIndex));
		data.fortressName = reader.getString(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_NAME, shipIndex));
		
		data.isTherePlanetToBuildABase = reader.getBool(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_PLANET_TO_BUILD_A_BASE, shipIndex));

		if (data.isTherePlanetToBuildABase) {
			data.planetToBuildABaseName = reader.getString(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_PLANET_TO_BUILD_A_BASE_NAME, shipIndex));			
		}

		data.requiredTitan = reader.getULongLong(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_REQUIRED_TITAN, shipIndex));
		data.fortressTitan = reader.getULongLong(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_SHIP_TITAN, shipIndex));

		ships.push_back(data);
    }

	std::list<fortress_build_information> bases;
	unsigned long baseCount = reader.getULong(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_COUNT);

    for (int baseIndex = 1; baseIndex < baseCount + 1; ++baseIndex) {
		fortress_build_information data;

		data.fortressId = reader.getId(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_ID, baseIndex));
		data.fortressName = reader.getString(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_NAME, baseIndex));

		data.isTherePlanetToBuildABase = reader.getBool(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_PLANET_TO_BUILD_A_BASE, baseIndex));

		if (data.isTherePlanetToBuildABase) {
			data.planetToBuildABaseName = reader.getString(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_PLANET_TO_BUILD_A_BASE_NAME, baseIndex));			
		}

		data.requiredTitan = reader.getULongLong(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_REQUIRED_TITAN, baseIndex));		
		data.fortressTitan = reader.getULongLong(create_param_name(REQUEST_PLAYER_FORTRESSES_BUILD_INFORMATION_ANSWER_BASE_TITAN, baseIndex));

		bases.push_back(data);
    }

	mainWindow_->answerFortressesBuildInformation(ships, bases);
}

void CommandClient::processPlayerFortresses(message * protocolMessage){
    ValueReader reader(protocolMessage);	

	std::vector<SimpleItem> fortresses;
	unsigned long fortressCount = reader.getULong(REQUEST_PLAYER_FORTRESSES_ANSWER_FORTRESS_COUNT);

    for (int fortressIndex = 1; fortressIndex < fortressCount + 1; ++fortressIndex) {
		SimpleItem data;

		data.id = reader.getId(create_param_name(REQUEST_PLAYER_FORTRESSES_ANSWER_FORTRESS_ID, fortressIndex));
		data.name = reader.getString(create_param_name(REQUEST_PLAYER_FORTRESSES_ANSWER_FORTRESS_NAME, fortressIndex));		
		data.fortressType = (EFortressType) reader.getULong(create_param_name(REQUEST_PLAYER_FORTRESSES_ANSWER_FORTRESS_TYPE, fortressIndex));		
		fortresses.push_back(data);
    }

	mainWindow_->answerFortresses(fortresses);
}

void CommandClient::playerFortresses() {
	socketClient_->sendAndFreeMessage(requestWriter::player_fortresses());
}

void CommandClient::playerFortressesWithBuildInformation() {
	socketClient_->sendAndFreeMessage(requestWriter::player_fortresses_build_information());
}

void CommandClient::conquerFortress(id_t selfFortressId, id_t enemyFortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::conquer_fortress(selfFortressId, enemyFortressId));
}

void CommandClient::processConquerFortress(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t selfFortressId = reader.getId(REQUEST_CONQUER_FORTRESS_ANSWER_SELF_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_CONQUER_FORTRESS_ANSWER_FAIL);
		mainWindow_->answerConquerFortressFAIL(selfFortressId, reason);
		return;
	}

	ConquerResultData data;

	data.selfFortressId = reader.getId(REQUEST_CONQUER_FORTRESS_ANSWER_SELF_FORTRESS_ID);
	data.enemyFortressId = reader.getId(REQUEST_CONQUER_FORTRESS_ANSWER_ENEMY_FORTRESS_ID);
	data.addingResult = (FortressAddingResult) reader.getULong(REQUEST_CONQUER_FORTRESS_ANSWER_FORTRESS_ADDING_RESULT);	

	data.isConquered = reader.getBool(REQUEST_CONQUER_FORTRESS_ANSWER_IS_CONQUERED);
	data.isDetailsAvailable = reader.getBool(REQUEST_CONQUER_FORTRESS_ANSWER_IS_DETAILS_AVAILABLE);
	data.isMainframeFailure = reader.getBool(REQUEST_CONQUER_FORTRESS_ANSWER_IS_MANFRAME_FAILURE);
	data.isEnergeticAccumulatorFailure = reader.getBool(REQUEST_CONQUER_FORTRESS_ANSWER_IS_ENERGETIC_ACCUMULATOR_FAILURE);
	data.energyInTarget = reader.getULongLong(REQUEST_CONQUER_FORTRESS_ANSWER_ENERGY_IN_TARGET);

	mainWindow_->answerConquerFortress(data);
}

void CommandClient::registerPlayer(const RegistrationData & data) {
    protocolWriter w;
    w.beginMessage(MT_REQUEST, REQUEST_REGISTER_PLAYER);
	w.writeValue(REQUEST_REGISTER_PLAYER_USERNAME, data.username);
	w.writeValue(REQUEST_REGISTER_PLAYER_PASSWORD, data.password);
	w.writeValue(REQUEST_REGISTER_PLAYER_REALNAME, data.realname);
    w.endMessage(true);

	socketClient_->sendAndFreeMessage(w.copyMessage());
}

void CommandClient::processRegisterPlayer(message * protocolMessage) {
    ValueReader reader(protocolMessage);

	RegistrationResult registrationResult;
	registrationResult.addingResult = (PlayerAddingResult) reader.getULong(REQUEST_REGISTER_PLAYER_ANSWER_ADDING_RESULT);
	registrationResult.username = reader.getString(REQUEST_REGISTER_PLAYER_ANSWER_USERNAME);
	registrationResult.password = reader.getString(REQUEST_REGISTER_PLAYER_ANSWER_PASSWORD);

	mainWindow_->answerRegistration(registrationResult);
}

void CommandClient::fortressAddAccommodations(id_t fortressId, unsigned long count, accommodation_type accommodationType) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_add_accommodations(fortressId, count, accommodationType));
}

void CommandClient::processFortressAddAccommodations(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_ADD_ACCOMMODATIONS_ANSWER_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_FORTRESS_ADD_ACCOMMODATIONS_ANSWER_FAIL);
		mainWindow_->answerFortressAddAccommodationsFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_FORTRESS_ADD_ACCOMMODATIONS_ANSWER_FORTRESS_ID);
	unsigned long count = reader.getULong(REQUEST_FORTRESS_ADD_ACCOMMODATIONS_ANSWER_ACCOMMODATION_COUNT);
	accommodation_type accommodationType = (accommodation_type) reader.getULong(REQUEST_FORTRESS_ADD_ACCOMMODATIONS_ANSWER_ACCOMMODATION_TYPE);

	mainWindow_->answerFortressAddAccommodations(fortressId, count, accommodationType);
}

void CommandClient::fortressAddCrew(id_t fortressId, unsigned long able, unsigned long wounded, crew_type crewType) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_add_crew(fortressId, able, wounded, crewType));
}

void CommandClient::fortressRemoveCrew(id_t fortressId, unsigned long able, unsigned long wounded, crew_type crewType) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_remove_crew(fortressId, able, wounded, crewType));
}

void CommandClient::processFortressAddCrew(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_ADD_CREW_ANSWER_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_FORTRESS_ADD_CREW_ANSWER_FAIL);
		mainWindow_->answerFortressAddCrewFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_FORTRESS_ADD_CREW_ANSWER_FORTRESS_ID);
	unsigned long ableCount = reader.getULong(REQUEST_FORTRESS_ADD_CREW_ANSWER_ABLE_COUNT);
	unsigned long woundedCount = reader.getULong(REQUEST_FORTRESS_ADD_CREW_ANSWER_WOUNDED_COUNT);
	crew_type crewType = (crew_type) reader.getULong(REQUEST_FORTRESS_ADD_CREW_ANSWER_CREW_TYPE);

	mainWindow_->answerFortressAddCrew(fortressId, ableCount, woundedCount, crewType);
}

void CommandClient::processFortressRemoveCrew(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_REMOVE_CREW_ANSWER_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_FORTRESS_REMOVE_CREW_ANSWER_FAIL);
		mainWindow_->answerFortressRemoveCrewFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_FORTRESS_REMOVE_CREW_ANSWER_FORTRESS_ID);
	unsigned long ableCount = reader.getULong(REQUEST_FORTRESS_REMOVE_CREW_ANSWER_ABLE_COUNT);
	unsigned long woundedCount = reader.getULong(REQUEST_FORTRESS_REMOVE_CREW_ANSWER_WOUNDED_COUNT);
	crew_type crewType = (crew_type) reader.getULong(REQUEST_FORTRESS_REMOVE_CREW_ANSWER_CREW_TYPE);

	mainWindow_->answerFortressRemoveCrew(fortressId, ableCount, woundedCount, crewType);
}

void CommandClient::processUpdateFortress(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	id_t fortressId = reader.getId(UPDATE_FORTRESS_FORTRESS_ID);

	mainWindow_->answerUpdateFortress(fortressId);
}

void CommandClient::gameSecondsPerActualSecond() {
	socketClient_->sendAndFreeMessage(requestWriter::game_seconds_per_actual_second());
}

void CommandClient::processGameSecondsPerActualSecond(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	mainWindow_->answerGameSecondsPerActualSecond(reader.getULong(REQUEST_GAME_SECONDS_PER_ACTUAL_SECOND_ANSWER_SECONDS));
}

void CommandClient::renameFortress(id_t fortressId, const std::string & newName) {
	socketClient_->sendAndFreeMessage(requestWriter::rename_fortress(fortressId, newName));
}

void CommandClient::processRenameFortress(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_RENAME_FORTRESS_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_RENAME_FORTRESS_ANSWER_FAIL);

		mainWindow_->answerRenameFortressFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_RENAME_FORTRESS_FORTRESS_ID);
	std::string newName = reader.getString(REQUEST_RENAME_FORTRESS_NEW_NAME);

	mainWindow_->answerRenameFortress(fortressId, newName);
}

void CommandClient::playerFortressesAttackInformation() {
	socketClient_->sendAndFreeMessage(requestWriter::player_fortresses_attack_information());
}

void CommandClient::processPlayerFortressesAttackInformation(message * protocolMessage){
    ValueReader reader(protocolMessage);	

	std::vector<fortress_attack_information> fortresses;
	unsigned long fortressCount = reader.getULong(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_COUNT);

    for (int fortressIndex = 1; fortressIndex < fortressCount + 1; ++fortressIndex) {
		fortress_attack_information data;

		readFortressFightData(reader, data.fortressFightData, fortressIndex);

		data.fortressInWeaponsTargetId = reader.getId(create_param_name(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_IN_WEAPONS_TARGET_ID, fortressIndex));

		if (data.fortressInWeaponsTargetId != 0) {
			data.fortressInWeaponsTargetName = reader.getString(create_param_name(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_IN_WEAPONS_TARGET_NAME, fortressIndex));
			data.fortressInWeaponsRangeTargetRealmName = reader.getString(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_IN_WEAPONS_TARGET_REALM_NAME);		
			data.fortressInWeaponsRangeTargetType = reader.getULong(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_IN_WEAPONS_TARGET_TYPE);		
		}

		unsigned long attackerCount = reader.getULong(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_ATTACKER_COUNT, fortressIndex);

		for (int index = 1; index < attackerCount + 1; ++index) {
			id_t attackerId = reader.getId(create_param_name(REQUEST_PLAYER_FORTRESSES_ATTACK_INFORMATION_ANSWER_FORTRESS_ATTACKER_ID, fortressIndex, index));
			data.attackers.push_back(attackerId);
		}
	
		fortresses.push_back(data);
    }

	mainWindow_->answerFortressesAttackInformation(fortresses);
}

void CommandClient::processHangarBuildItem(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_HANGAR_BUILD_ITEM_ANSWER_FORTRESSID);
		id_t hangarId = reader.getId(REQUEST_HANGAR_BUILD_ITEM_ANSWER_HANGAR_ID);
		std::string reason = reader.getString(REQUEST_HANGAR_BUILD_ITEM_ANSWER_FAIL);

		mainWindow_->answerHangarBuildItemFAIL(fortressId, hangarId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_HANGAR_BUILD_ITEM_ANSWER_FORTRESSID);
	id_t hangarId = reader.getId(REQUEST_HANGAR_BUILD_ITEM_ANSWER_HANGAR_ID);
	std::string result = reader.getString(REQUEST_HANGAR_BUILD_ITEM_ANSWER_CREATION_RESULT);

	mainWindow_->answerHangarBuildItem(fortressId, hangarId, result);
}

void CommandClient::processHangarCancelItem(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_HANGAR_CANCEL_ITEM_ANSWER_FORTRESSID);
		id_t hangarId = reader.getId(REQUEST_HANGAR_CANCEL_ITEM_ANSWER_HANGAR_ID);
		std::string reason = reader.getString(REQUEST_HANGAR_CANCEL_ITEM_ANSWER_FAIL);

		mainWindow_->answerHangarCancelItemFAIL(fortressId, hangarId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_HANGAR_CANCEL_ITEM_ANSWER_FORTRESSID);
	id_t hangarId = reader.getId(REQUEST_HANGAR_CANCEL_ITEM_ANSWER_HANGAR_ID);

	mainWindow_->answerHangarCancelItem(fortressId, hangarId);
}

void CommandClient::processHangarBuildShip(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_HANGAR_BUILD_SHIP_ANSWER_FORTRESSID);
		id_t hangarId = reader.getId(REQUEST_HANGAR_BUILD_SHIP_ANSWER_HANGAR_ID);
		std::string reason = reader.getString(REQUEST_HANGAR_BUILD_SHIP_ANSWER_FAIL);

		mainWindow_->answerHangarBuildShipFAIL(fortressId, hangarId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_HANGAR_BUILD_SHIP_ANSWER_FORTRESSID);
	id_t hangarId = reader.getId(REQUEST_HANGAR_BUILD_SHIP_ANSWER_HANGAR_ID);
	std::string result = reader.getString(REQUEST_HANGAR_BUILD_SHIP_ANSWER_CREATION_RESULT);

	mainWindow_->answerHangarBuildShip(fortressId, hangarId, result);
}

void CommandClient::hangarBuildShip(id_t fortressId, id_t hangarId, id_t fortressClassId, unsigned long long buildingTitanium) {
	socketClient_->sendAndFreeMessage(requestWriter::base_hangar_build_ship(fortressId, hangarId, fortressClassId, buildingTitanium));
}

void CommandClient::updateFortressSensorsInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_sensors_information(fortressId));
}

void CommandClient::updateFortressCloakingInformation(id_t fortressId) {
	socketClient_->sendAndFreeMessage(requestWriter::fortress_cloaking_information(fortressId));
}

void CommandClient::readSensorsData(ValueReader & reader, const std::string & prefix, sensors_data & data) {
	data.available = reader.getBool(create_param_name(prefix, REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_AVAILABLE));
	data.range = reader.getDouble(create_param_name(prefix, REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_RANGE));
	data.consumption = reader.getDouble(create_param_name(prefix, REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_CONSUMPTION));
	data.level = reader.getULong(create_param_name(prefix, REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_LEVEL));
	data.status = reader.getDouble(create_param_name(prefix, REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_STATUS));
	data.weight = reader.getULongLong(create_param_name(prefix, REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_WEIGHT));
}

void CommandClient::processUpdateFortressSensorsInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_SENSORS_INFORMATION_SELF_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_FORTRESS_SENSORS_INFORMATION_ANSWER_FAIL);

		mainWindow_->answerUpdateFortressSensorsFAIL(fortressId, reason);
		return;
	}

	id_t fortressId = reader.getId(REQUEST_FORTRESS_SENSORS_INFORMATION_SELF_FORTRESS_ID);
	sensors_data sensors;
	readSensorsData(reader, REQUEST_FORTRESS_SENSORS_INFORMATION_HR_PREFIX, sensors);

	sensors_data lrSensors;
	readSensorsData(reader, REQUEST_FORTRESS_SENSORS_INFORMATION_LR_PREFIX, lrSensors);

	mainWindow_->answerUpdateFortressSensors(fortressId, sensors, lrSensors);
}

void CommandClient::processUpdateFortressCloakingInformation(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	if (!reader.isAnswerOk()) {
		id_t fortressId = reader.getId(REQUEST_FORTRESS_CLOAKING_INFORMATION_SELF_FORTRESS_ID);
		std::string reason = reader.getString(REQUEST_FORTRESS_CLOAKING_INFORMATION_ANSWER_FAIL);

		mainWindow_->answerUpdateFortressCloakingFAIL(fortressId, reason);
		return;
	}

	cloaking_data data;

	id_t fortressId = reader.getId(REQUEST_FORTRESS_CLOAKING_INFORMATION_SELF_FORTRESS_ID);

	data.available = reader.getBool(REQUEST_FORTRESS_CLOAKING_INFORMATION_ANSWER_AVAILABLE);
	data.consumption = reader.getDouble(REQUEST_FORTRESS_CLOAKING_INFORMATION_ANSWER_CONSUMPTION);
	data.level = reader.getULong(REQUEST_FORTRESS_CLOAKING_INFORMATION_ANSWER_LEVEL);
	data.status = reader.getDouble(REQUEST_FORTRESS_CLOAKING_INFORMATION_ANSWER_STATUS);
	data.weight = reader.getULongLong(REQUEST_FORTRESS_CLOAKING_INFORMATION_ANSWER_WEIGHT);

	mainWindow_->answerUpdateFortressCloaking(fortressId, data);
}

void CommandClient::processFightProgressReport(message * protocolMessage) {
	ValueReader reader(protocolMessage);

	fight_progress_report report;

	report.deflectorShieldsEnergyLoss = reader.getULongLong(FIGHT_PROGRESS_REPORT_DEFLECTOR_SHIELDS_ENERGY_LOSS);
	report.deflectorShieldsEnergyLossPerc = reader.getDouble(FIGHT_PROGRESS_REPORT_DEFLECTOR_SHIELDS_ENERGY_LOSS_PERC);
	report.disruptiveBreakdown = reader.getBool(FIGHT_PROGRESS_REPORT_DISRUPTIVE_BREAKDOWN);
	report.attackResult = reader.getULong(FIGHT_PROGRESS_REPORT_ATTACK_RESULT);
	report.structuralIntegrityLoss = reader.getULongLong(FIGHT_PROGRESS_REPORT_INTEGRITY_ENERGY_LOSS);
	report.structuralIntegrityLossPerc = reader.getDouble(FIGHT_PROGRESS_REPORT_INTEGRITY_ENERGY_LOSS_PERC);

	report.isAttacker = reader.getBool(FIGHT_PROGRESS_REPORT_IS_ATTACKER);
	report.isDefender = reader.getBool(FIGHT_PROGRESS_REPORT_IS_DEFENDER);

	report.attackerExists = reader.getBool(FIGHT_PROGRESS_REPORT_ATTACKER_EXISTS);

	if (report.attackerExists) {
		report.attackerFortressId = reader.getId(FIGHT_PROGRESS_REPORT_ATTACKER_FORTRESS_ID);
		report.attackerFortressName = reader.getString(FIGHT_PROGRESS_REPORT_ATTACKER_FORTRESS_NAME);
		report.attackerRealmName = reader.getString(FIGHT_PROGRESS_REPORT_ATTACKER_FORTRESS_REALM_NAME);;
		report.isAttackerShip = reader.getBool(FIGHT_PROGRESS_REPORT_ATTACKER_SHIP);
	}

	report.defenderExists = reader.getBool(FIGHT_PROGRESS_REPORT_DEFENDER_EXISTS);

	if (report.defenderExists) {
		report.defenderFortressId = reader.getId(FIGHT_PROGRESS_REPORT_DEFENDER_FORTRESS_ID);
		report.defenderFortressName = reader.getString(FIGHT_PROGRESS_REPORT_DEFENDER_FORTRESS_NAME);
		report.defenderRealmName = reader.getString(FIGHT_PROGRESS_REPORT_DEFENDER_FORTRESS_REALM_NAME);;
		report.isDefenderShip = reader.getBool(FIGHT_PROGRESS_REPORT_DEFENDER_SHIP);
	}

	readFortressFightData(reader, report.fortressFightData, 1);

	mainWindow_->answerFightProgressReport(report);
}

void CommandClient::readFortressFightData(ValueReader & reader, fortress_detailed_fight_data & data, unsigned long index) {
	data.id = reader.getId(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_ID, index));
	data.name = reader.getString(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_NAME, index));
	data.type = reader.getULong(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_TYPE, index));
	data.actualStructuralIntegrity = reader.getULongLong(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_ACTUAL_INTEGRITY, index));
	data.totalStructuralIntegrity = reader.getULongLong(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_TOTAL_INTEGRITY, index));
	data.structuralIntegrityGradient = reader.getDouble(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_INTEGRITY_GRADIENT, index));
	data.shieldsEnergy = reader.getULongLong(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_SHIELDS_ENERGY, index));
	data.shieldsActualAccumulator = reader.getULongLong(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_SHIELDS_ACCUMULATOR, index));
	data.shieldsClientAccumulator = reader.getULongLong(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_SHIELDS_CLIENT_ACCUMULATOR, index));
	data.shieldsGradient = reader.getDouble(create_param_name(FORTRESS_DETAILED_FIGHT_DATA_FORTRESS_SHIELDS_GRADIENT, index));
}