#include "fortress_skelet.h"

#include <cassert>
//#include <typeinfo>
#include <cmath>
#include <algorithm>
#include <set>
#include <limits>

#ifdef _DEBUG
#include <sstream>
#include "log.h"
#endif

#include "error_handling.h"
#include "time_mapping.h"
#include "independent_constants.h"
#include "physics.h"

#include "context.h"
#include "space.h"
#include "spaceindex.h"
#include "time_axis.h"
#include "cache_data.h"
#include "players_realms.h"
#include "prot_srv.h"

#ifdef _DEBUG
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#endif

// ################################
// ################################

// --------------------------------

void fortressClass::thisFortressHasBeenAnnihilated(fortressClass * enemy)
{
	/* POZOR, OBJEKT ENEMY ZAHY ZANIKNE, TAKZE SI HO NIKDO NIKDE NESCHOVAVEJTE */
	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), answerWriter::fight_action_report(this, enemy, FIGHT_ACTION_THIS_FORTRESS_HAS_BEEN_ANNIHILATED));
};

// --------------------------------

void fortressClass::weaponsTargetHasBeenAnnihilated(fortressClass * enemy)
{
	/* POZOR, OBJEKT ENEMY ZAHY ZANIKNE, TAKZE SI HO NIKDO NIKDE NESCHOVAVEJTE */
	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), answerWriter::fight_action_report(this, enemy, FIGHT_ACTION_WEAPONS_TARGET_HAS_BEEN_ANNIHILATED));
};

// --------------------------------

void fortressClass::enemyWeaponsLockedOnWarning(fortressClass * enemy)
{
	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), answerWriter::fight_action_report(this, enemy, FIGHT_ACTION_ENEMY_WEAPONS_LOCKED_ON_WARNING));
};

// --------------------------------

void fortressClass::enemyWeaponsUnlocked(fortressClass * enemy)
{
	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), answerWriter::fight_action_report(this, enemy, FIGHT_ACTION_ENEMY_WEAPONS_UNLOCKED));
};



// --------------------------------

void fortressClass::ourWeaponsLockedOnEnemy(fortressClass * enemy)
{
	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), answerWriter::fight_action_report(this, enemy, FIGHT_ACTION_OUR_WEAPONS_LOCKED_ON_ENEMY));
};

// --------------------------------

void fortressClass::ourWeaponsUnlocked(fortressClass * enemy)
{
	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), answerWriter::fight_action_report(this, enemy, FIGHT_ACTION_OUR_WEAPONS_UNLOCKED));
};

// --------------------------------

void fortressClass::sendAttackReport(attackReportClass * report)
{
	fight_progress_report clientReport;
	
	protocolWriter w;

	w.beginMessage(MT_ANSWER, FIGHT_PROGRESS_REPORT);

	w.writeValue(FIGHT_PROGRESS_REPORT_DEFLECTOR_SHIELDS_ENERGY_LOSS, report->deflectorShieldsEnergyLoss);
	w.writeValue(FIGHT_PROGRESS_REPORT_DEFLECTOR_SHIELDS_ENERGY_LOSS_PERC, report->deflectorShieldsEnergyLossPerc);
	w.writeValue(FIGHT_PROGRESS_REPORT_DISRUPTIVE_BREAKDOWN, report->disruptiveBreakdown);
	w.writeValue(FIGHT_PROGRESS_REPORT_ATTACK_RESULT, (unsigned long) report->result);
	w.writeValue(FIGHT_PROGRESS_REPORT_INTEGRITY_ENERGY_LOSS, report->structuralIntegrityLoss);
	w.writeValue(FIGHT_PROGRESS_REPORT_INTEGRITY_ENERGY_LOSS_PERC, report->structuralIntegrityLossPerc);

	bool offensiveReport = report->offensiveReport(this);
	bool defensiveReport = report->defensiveReport(this);

	w.writeValue(FIGHT_PROGRESS_REPORT_IS_ATTACKER, offensiveReport);
	w.writeValue(FIGHT_PROGRESS_REPORT_IS_DEFENDER, defensiveReport);

	fortressClass * attacker = report->getAttacker();

	if (attacker != NULL) {
		w.writeValue(FIGHT_PROGRESS_REPORT_ATTACKER_EXISTS, true);
		w.writeValue(FIGHT_PROGRESS_REPORT_ATTACKER_FORTRESS_ID, attacker->getID());
		w.writeValue(FIGHT_PROGRESS_REPORT_ATTACKER_FORTRESS_NAME, attacker->getFortressName());
		w.writeValue(FIGHT_PROGRESS_REPORT_ATTACKER_FORTRESS_REALM_NAME, attacker->getFortressRealm()->getPlayerName());
		w.writeValue(FIGHT_PROGRESS_REPORT_ATTACKER_SHIP, attacker->getFortressType() == FT_SHIP);
	}
	else {
		w.writeValue(FIGHT_PROGRESS_REPORT_ATTACKER_EXISTS, false);
	}

	fortressClass * defender = report->getDefender();

	if (defender != NULL) {
		w.writeValue(FIGHT_PROGRESS_REPORT_DEFENDER_EXISTS, true);
		w.writeValue(FIGHT_PROGRESS_REPORT_DEFENDER_FORTRESS_ID, defender->getID());
		w.writeValue(FIGHT_PROGRESS_REPORT_DEFENDER_FORTRESS_NAME, defender->getFortressName());
		w.writeValue(FIGHT_PROGRESS_REPORT_DEFENDER_FORTRESS_REALM_NAME, defender->getFortressRealm()->getPlayerName());
		w.writeValue(FIGHT_PROGRESS_REPORT_DEFENDER_SHIP, defender->getFortressType() == FT_SHIP);
	}
	else {
		w.writeValue(FIGHT_PROGRESS_REPORT_DEFENDER_EXISTS, false);
	}

	answerWriter::write_fortress_detailed_fight_data(w, this, 1);

    w.endMessage(true);
    char * msg = w.copyMessage();

	gctx.sendToClient(make_pair(this->getFortressRealmID(), 0), msg);
};