/**
 * Prepares debriefing: gathers Aliens, Corpses, Artefacts, UFO Components.
 * Adds the items to the craft.
 * Also calculates the soldiers experience, and possible promotions.
 * If aborted, only the things on the exit area are recovered.
 */
void DebriefingState::prepareDebriefing()
{
	_stats.push_back(new DebriefingStat("STR_ALIENS_KILLED", false));
	_stats.push_back(new DebriefingStat("STR_ALIEN_CORPSES_RECOVERED", false));
	_stats.push_back(new DebriefingStat("STR_LIVE_ALIENS_RECOVERED", false));
	_stats.push_back(new DebriefingStat("STR_ALIEN_ARTIFACTS_RECOVERED", false));
	_stats.push_back(new DebriefingStat("STR_ALIEN_BASE_CONTROL_DESTROYED", false));
	_stats.push_back(new DebriefingStat("STR_CIVILIANS_KILLED_BY_ALIENS", false));
	_stats.push_back(new DebriefingStat("STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES", false));
	_stats.push_back(new DebriefingStat("STR_CIVILIANS_SAVED", false));
	_stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_KILLED", false));
	//_stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_RETIRED_THROUGH_INJURY", false));
	_stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_MISSING_IN_ACTION", false));
	_stats.push_back(new DebriefingStat("STR_TANKS_DESTROYED", false));
	_stats.push_back(new DebriefingStat("STR_XCOM_CRAFT_LOST", false));
	_stats.push_back(new DebriefingStat("STR_UFO_POWER_SOURCE", true));
	_stats.push_back(new DebriefingStat("STR_UFO_NAVIGATION", true));
	_stats.push_back(new DebriefingStat("STR_UFO_CONSTRUCTION", true));
	_stats.push_back(new DebriefingStat("STR_ALIEN_FOOD", true));
	_stats.push_back(new DebriefingStat("STR_ALIEN_REPRODUCTION", true));
	_stats.push_back(new DebriefingStat("STR_ALIEN_ENTERTAINMENT", true));
	_stats.push_back(new DebriefingStat("STR_ALIEN_SURGERY", true));
	_stats.push_back(new DebriefingStat("STR_EXAMINATION_ROOM", true));
	_stats.push_back(new DebriefingStat("STR_ALIEN_ALLOYS", true));
	_stats.push_back(new DebriefingStat("STR_ELERIUM_115", true));

	SavedGame *save = _game->getSavedGame();
	SavedBattleGame *battle = save->getBattleGame();
	bool aborted = battle->isAborted();
	Craft* craft = 0;
	std::vector<Craft*>::iterator craftIterator;
	Base* base = 0;

	int playerInExitArea = 0; // if this stays 0 the craft is lost...
	int playersSurvived = 0; // if this stays 0 the craft is lost...

	for (std::vector<Base*>::iterator i = save->getBases()->begin(); i != save->getBases()->end(); ++i)
	{

		// in case we have a craft - check which craft it is about
		for (std::vector<Craft*>::iterator j = (*i)->getCrafts()->begin(); j != (*i)->getCrafts()->end(); ++j)
		{
			if ((*j)->isInBattlescape())
			{
				craft = (*j);
				base = (*i);
				craftIterator = j;
				craft->returnToBase();
				craft->setLowFuel(true);
				craft->setInBattlescape(false);
			}
		}
	}

	// UFO crash/landing site disappears
	for (std::vector<Ufo*>::iterator i = save->getUfos()->begin(); i != save->getUfos()->end(); ++i)
	{
		if ((*i)->isInBattlescape())
		{
			delete *i;
			save->getUfos()->erase(i);
			break;
		}
	}

	// lets see what happens with units
	for (std::vector<BattleUnit*>::iterator j = battle->getUnits()->begin(); j != battle->getUnits()->end(); ++j)
	{
		UnitStatus status = (*j)->getStatus();
		UnitFaction faction = (*j)->getFaction();
		int value = (*j)->getValue();
		Soldier *soldier = save->getSoldier((*j)->getId());

		if (status == STATUS_DEAD)
		{
			if (faction == FACTION_HOSTILE)
			{
				addStat("STR_ALIENS_KILLED", 1, value);
			}
			if (faction == FACTION_PLAYER)
			{
				if (soldier != 0)
				{
					addStat("STR_XCOM_OPERATIVES_KILLED", 1, -value);
					for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i)
					{
						if ((*i) == soldier)
						{
							delete (*i);
							base->getSoldiers()->erase(i);
							break;
						}
					}
				}
				else
				{
					// non soldier player = tank
					addStat("STR_TANKS_DESTROYED", 1, -value);
				}
			}
		}
		else if (status == STATUS_UNCONSCIOUS)
		{
			if (faction == FACTION_HOSTILE && (!aborted || (*j)->isInExitArea()))
			{
				addStat("STR_LIVE_ALIENS_RECOVERED", 1, value);
			}
		}
		else if (faction == FACTION_PLAYER)
		{
			playersSurvived++;
			if ((*j)->isInExitArea() || !aborted)
			{
				playerInExitArea++;
				(*j)->postMissionProcedures(save);
			}
			else
			{
				addStat("STR_XCOM_OPERATIVES_MISSING_IN_ACTION", 1, -value);
				for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i)
				{
					if ((*i) == soldier)
					{
						delete (*i);
						base->getSoldiers()->erase(i);
						break;
					}
				}
			}
		}
	}
	if (((playerInExitArea == 0 && aborted) || (playersSurvived == 0)) && craft != 0)
	{
		addStat("STR_XCOM_CRAFT_LOST", 1, -200);
		delete craft;
		base->getCrafts()->erase(craftIterator);
		for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end();)
		{
			if ((*i)->getCraft() == craft)
			{
				delete (*i);
				i = base->getSoldiers()->erase(i);
			}
			else
			{
				 ++i;
			}
		}
		_txtTitle->setText(_game->getLanguage()->getString("STR_CRAFT_IS_LOST"));
		return;
	}

	if (!aborted && playersSurvived > 0) 	// RECOVER UFO : run through all tiles to recover UFO components and items
	{
		if (battle->getMissionType() == "STR_BASE_DEFENCE")
		{
			_txtTitle->setText(_game->getLanguage()->getString("STR_BASE_IS_SAVED"));
		}
		else
		{
			_txtTitle->setText(_game->getLanguage()->getString("STR_UFO_IS_RECOVERED"));
		}

		for (int i = 0; i < battle->getHeight() * battle->getLength() * battle->getWidth(); ++i)
		{
			for (int part = 0; part < 4; part++)
			{
				if (battle->getTiles()[i]->getMapData(part))
				{
					switch (battle->getTiles()[i]->getMapData(part)->getSpecialType())
					{
					case UFO_POWER_SOURCE:
						addStat("STR_UFO_POWER_SOURCE", 1, 1); break;
					case DESTROY_OBJECTIVE:break; // this is the brain
					case UFO_NAVIGATION:
						addStat("STR_UFO_NAVIGATION", 1, 1); break;
					case ALIEN_FOOD:
						addStat("STR_ALIEN_FOOD", 1, 1); break;
					case ALIEN_REPRODUCTION:
						addStat("STR_ALIEN_REPRODUCTION", 1, 1); break;
					case ALIEN_ENTERTAINMENT:
						addStat("STR_ALIEN_ENTERTAINMENT", 1, 1); break;
					case ALIEN_SURGERY:
						addStat("STR_ALIEN_SURGERY", 1, 1); break;
					case UNKNOWN09:
						addStat("STR_UFO_CONSTRUCTION", 1, 1); break;
					case ALIEN_ALLOYS:
						addStat("STR_ALIEN_ALLOYS", 1, 1); break;
					case EXAM_ROOM:
						addStat("STR_EXAMINATION_ROOM", 1, 1); break;
					}

				}
			}
		}

		// alien alloys recovery values are divided by 10 or divided by 150 in case of an alien base
		int divider = battle->getMissionType()=="STR_ALIEN_BASE_ASSAULT"?150:10;
		for (std::vector<DebriefingStat*>::iterator i = _stats.begin(); i != _stats.end(); ++i)
		{
			if ((*i)->item == "STR_ALIEN_ALLOYS")
			{
				(*i)->qty = (*i)->qty / divider;
				(*i)->score = (*i)->score / divider;
				break;
			}

			/*if ((*i)->recovery && (*i)->qty > 0)
			{
				base->getItems()->addItem((*i)->item, (*i)->qty);
			}*/
		}
	}
	else
	{
		if (battle->getMissionType() == "STR_BASE_DEFENCE")
		{
			_txtTitle->setText(_game->getLanguage()->getString("STR_BASE_IS_LOST"));
		}
		else
		{
			_txtTitle->setText(_game->getLanguage()->getString("STR_UFO_IS_NOT_RECOVERED"));
		}
	}

}
/**
 * Starts the battle.
 * @param action Pointer to an action.
 */
void NewBattleState::btnOkClick(Action *)
{
	save();
	if (_missionTypes[_cbxMission->getSelected()] != "STR_BASE_DEFENSE" && _craft->getNumSoldiers() == 0 && _craft->getNumVehicles() == 0)
	{
		return;
	}

	SavedBattleGame *bgame = new SavedBattleGame();
	_game->getSavedGame()->setBattleGame(bgame);
	bgame->setMissionType(_missionTypes[_cbxMission->getSelected()]);
	BattlescapeGenerator bgen = BattlescapeGenerator(_game);
	Base *base = 0;

	bgen.setTerrain(_game->getMod()->getTerrain(_terrainTypes[_cbxTerrain->getSelected()]));

	// base defense
	if (_missionTypes[_cbxMission->getSelected()] == "STR_BASE_DEFENSE")
	{
		base = _craft->getBase();
		bgen.setBase(base);
		_craft = 0;
	}
	// alien base
	else if (_game->getMod()->getDeployment(bgame->getMissionType())->isAlienBase())
	{
		AlienBase *b = new AlienBase(_game->getMod()->getDeployment(bgame->getMissionType()));
		b->setId(1);
		b->setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);
		_craft->setDestination(b);
		bgen.setAlienBase(b);
		_game->getSavedGame()->getAlienBases()->push_back(b);
	}
	// ufo assault
	else if (_craft && _game->getMod()->getUfo(_missionTypes[_cbxMission->getSelected()]))
	{
		Ufo *u = new Ufo(_game->getMod()->getUfo(_missionTypes[_cbxMission->getSelected()]));
		u->setId(1);
		_craft->setDestination(u);
		bgen.setUfo(u);
		// either ground assault or ufo crash
		if (RNG::generate(0,1) == 1)
		{
			u->setStatus(Ufo::LANDED);
			bgame->setMissionType("STR_UFO_GROUND_ASSAULT");
		}
		else
		{
			u->setStatus(Ufo::CRASHED);
			bgame->setMissionType("STR_UFO_CRASH_RECOVERY");
		}
		_game->getSavedGame()->getUfos()->push_back(u);
	}
	// mission site
	else
	{
		const AlienDeployment *deployment = _game->getMod()->getDeployment(bgame->getMissionType());
		const RuleAlienMission *mission = _game->getMod()->getAlienMission(_game->getMod()->getAlienMissionList().front()); // doesn't matter
		MissionSite *m = new MissionSite(mission, deployment);
		m->setId(1);
		m->setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);
		_craft->setDestination(m);
		bgen.setMissionSite(m);
		_game->getSavedGame()->getMissionSites()->push_back(m);
	}

	if (_craft)
	{
		_craft->setSpeed(0);
		bgen.setCraft(_craft);
	}

	_game->getSavedGame()->setDifficulty((GameDifficulty)_cbxDifficulty->getSelected());

	bgen.setWorldShade(_slrDarkness->getValue());
	bgen.setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);
	bgen.setAlienItemlevel(_slrAlienTech->getValue());
	bgame->setDepth(_slrDepth->getValue());

	bgen.run();

	_game->popState();
	_game->popState();
	_game->pushState(new BriefingState(_craft, base));
	_craft = 0;
}