/**
 * @file
 * @brief Header file for single player campaign control.
 */

/*
Copyright (C) 2002-2013 UFO: Alien Invasion.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#pragma once

extern memPool_t* cp_campaignPool;

struct aircraft_s;
struct installation_s;
class Employee;
struct ugv_s;
struct campaign_s;

#define MAX_CAMPAIGNS	16

#define MAX_ASSEMBLIES	16

/* fraction of nation that can be below min happiness before the game is lost */
#define NATIONBELOWLIMITPERCENTAGE 0.5f

/** @todo rename this after merging with savegame breakage branch and also change the value to -1 */
#define	BYTES_NONE	0xFF

#include "cp_cgame_callbacks.h"
#include "cp_rank.h"
#include "cp_save.h"
#include "cp_parse.h"
#include "cp_event.h"
#include "cp_ufopedia.h"
#include "cp_research.h"
#include "cp_radar.h"
#include "cp_aircraft.h"
#include "cp_base.h"
#include "cp_employee.h"
#include "cp_transfer.h"
#include "cp_nation.h"
#include "cp_installation.h"
#include "cp_produce.h"
#include "cp_uforecovery.h"
#include "cp_airfight.h"
#include "cp_messageoptions.h"
#include "cp_alienbase.h"
#include "cp_market.h"
#include "cp_statistics.h"

/* check for water */
/* blue value is 64 */
#define MapIsWater(color)        (color[0] ==   0 && color[1] ==   0 && color[2] ==  64)

/* terrain types */
#define MapIsArctic(color)       (color[0] == 128 && color[1] == 255 && color[2] == 255)
#define MapIsDesert(color)       (color[0] == 255 && color[1] == 128 && color[2] ==   0)
#define MapIsMountain(color)     (color[0] == 255 && color[1] ==   0 && color[2] ==   0)
#define MapIsTropical(color)     (color[0] == 128 && color[1] == 128 && color[2] == 255)
#define MapIsGrass(color)        (color[0] == 128 && color[1] == 255 && color[2] ==   0)
#define MapIsWasted(color)       (color[0] == 128 && color[1] ==   0 && color[2] == 128)
#define MapIsCold(color)         (color[0] ==   0 && color[1] ==   0 && color[2] == 255)

/* culture types */
#define MapIsWestern(color)      (color[0] == 128 && color[1] == 255 && color[2] == 255)
#define MapIsEastern(color)      (color[0] == 255 && color[1] == 128 && color[2] ==   0)
#define MapIsOriental(color)     (color[0] == 255 && color[1] ==   0 && color[2] ==   0)
#define MapIsAfrican(color)      (color[0] == 128 && color[1] == 128 && color[2] == 255)

/* population types */
#define MapIsUrban(color)        (color[0] == 128 && color[1] == 255 && color[2] == 255)
#define MapIsSuburban(color)     (color[0] == 255 && color[1] == 128 && color[2] ==   0)
#define MapIsVillage(color)      (color[0] == 255 && color[1] ==   0 && color[2] ==   0)
#define MapIsRural(color)        (color[0] == 128 && color[1] == 128 && color[2] == 255)
#define MapIsNopopulation(color) (color[0] == 128 && color[1] == 255 && color[2] ==   0)

/* RASTER enables a better performance for CP_GetRandomPosOnGeoscapeWithParameters set it to 1-6
 * the higher the value the better the performance, but the smaller the coverage */
#define RASTER 2

/* nation happiness constants */
#define HAPPINESS_SUBVERSION_LOSS			-0.15
#define HAPPINESS_ALIEN_MISSION_LOSS		-0.02
#define HAPPINESS_UFO_SALE_GAIN				0.02
#define HAPPINESS_UFO_SALE_LOSS				0.005
#define HAPPINESS_MAX_MISSION_IMPACT		0.07

/* Maximum alien groups per alien team category */
#define MAX_ALIEN_GROUP_PER_CATEGORY	8
/* Maximum alien team category defined in scripts */
#define ALIENCATEGORY_MAX	64
#define BID_FACTOR 0.9
#define MAX_PROJECTILESONGEOSCAPE 32

/**
 * @brief The amount of time (in hours) it takes for the interest to increase by 1. Is later affected by difficulty.
 */
#define HOURS_PER_ONE_INTEREST				24

/**
 * @brief Determines the interest interval for a single campaign
 */
#define INITIAL_OVERALL_INTEREST 			20
#define FINAL_OVERALL_INTEREST 				400

/**
 * @brief The length of a single mission spawn cycle
 */
#define DELAY_BETWEEN_MISSION_SPAWNING 		12

/**
 * @brief Determines the early game period during which DELAY_BETWEEN_MISSION_SPAWNING is halved.
 * @note This is done to ensure the player is not bored early in the game. The rush will stop when alien interest reaches this level.
 */
#define EARLY_UFO_RUSH_INTEREST 			50

/**
 * @brief The minimum and maximum amount of missions per mission cycle.
 * @note some of the missions can be non-occurrence missions.
 */
#define MINIMUM_MISSIONS_PER_CYCLE 			5
#define MAXIMUM_MISSIONS_PER_CYCLE 			17

/**
 * @brief The probability that any new alien mission will be a non-occurrence mission.
 */
#define NON_OCCURRENCE_PROBABILITY 			0.75

/** possible map types */
typedef enum mapType_s {
	MAPTYPE_TERRAIN,
	MAPTYPE_CULTURE,
	MAPTYPE_POPULATION,
	MAPTYPE_NATIONS,

	MAPTYPE_MAX
} mapType_t;

/** @brief possible mission detection status */
typedef enum missionDetectionStatus_s {
	MISDET_CANT_BE_DETECTED,		/**< Mission can't be seen on geoscape */
	MISDET_ALWAYS_DETECTED,			/**< Mission is seen on geoscape, whatever it's position */
	MISDET_MAY_BE_DETECTED			/**< Mission may be seen on geoscape, if a probability test is done */
} missionDetectionStatus_t;

/** possible campaign interest categories: type of missions that aliens can undertake */
typedef enum interestCategory_s {
	INTERESTCATEGORY_NONE,			/**< No mission */
	INTERESTCATEGORY_RECON,			/**< Aerial recon mission or ground mission (UFO may or not land) */
	INTERESTCATEGORY_TERROR_ATTACK,	/**< Terror attack */
	INTERESTCATEGORY_BASE_ATTACK,	/**< Alien attack a phalanx base */
	INTERESTCATEGORY_BUILDING,		/**< Alien build a new base or subverse governments */
	INTERESTCATEGORY_SUPPLY,		/**< Alien supply one of their bases */
	INTERESTCATEGORY_XVI,			/**< Alien try to spread XVI */
	INTERESTCATEGORY_INTERCEPT,		/**< Alien try to intercept PHALANX aircraft */
	INTERESTCATEGORY_HARVEST,		/**< Alien try to harvest */
	INTERESTCATEGORY_ALIENBASE,		/**< Alien base already built on earth
									 * @note This is not a mission alien can undertake, but the result of
									 * INTERESTCATEGORY_BUILDING */
	INTERESTCATEGORY_UFOCARRIER,	/**< UFO-Carrier is detected */
	INTERESTCATEGORY_RESCUE,

	INTERESTCATEGORY_MAX
} interestCategory_t;

/** possible stage for campaign missions (i.e. possible actions for UFO) */
typedef enum missionStage_s {
	STAGE_NOT_ACTIVE,				/**< mission did not begin yet */
	STAGE_COME_FROM_ORBIT,			/**< UFO is arriving */

	STAGE_RECON_AIR,				/**< Aerial Recon */
	STAGE_MISSION_GOTO,				/**< Going to a new position */
	STAGE_RECON_GROUND,				/**< Ground Recon */
	STAGE_TERROR_MISSION,			/**< Terror mission */
	STAGE_BUILD_BASE,				/**< Building a base */
	STAGE_BASE_ATTACK,				/**< Base attack */
	STAGE_SUBVERT_GOV,				/**< Subvert government */
	STAGE_SUPPLY,					/**< Supply already existing base */
	STAGE_SPREAD_XVI,				/**< Spreading XVI Virus */
	STAGE_INTERCEPT,				/**< UFO attacks any encountered PHALANX aircraft or attack an installation */
	STAGE_BASE_DISCOVERED,			/**< PHALANX discovered the base */
	STAGE_HARVEST,					/**< Harvesting */

	STAGE_RETURN_TO_ORBIT,			/**< UFO is going back to base */

	STAGE_OVER						/**< Mission is over */
} missionStage_t;

/** @brief alien team group definition.
 * @note This is the definition of one groups of aliens (several races) that can
 * be used on the same map.
 * @sa alienTeamCategory_s
 */
typedef struct alienTeamGroup_s {
	int idx;			/**< idx of the group in the alien team category */
	int categoryIdx;	/**< idx of category it's used in */
	int minInterest;	/**< Minimum interest value this group should be used with. */
	int maxInterest;	/**< Maximum interest value this group should be used with. */
	int minAlienCount;	/**< Minimum number of aliens in this group */
	int maxAlienCount;	/**< Maximum number of aliens in this group */

	const teamDef_t* alienTeams[MAX_TEAMS_PER_MISSION];	/**< different alien teams available
													 * that will be used in mission */
	const chrTemplate_t* alienChrTemplates[MAX_TEAMS_PER_MISSION];
	int numAlienTeams;		/**< Number of alienTeams defined in this group. */
} alienTeamGroup_t;

/** @brief alien team category definition
 * @note This is the definition of all groups of aliens that can be used for
 * a mission category
 * @sa alienTeamGroup_s
 */
typedef struct alienTeamCategory_s {
	char id[MAX_VAR];			/**< id of the category */
	interestCategory_t missionCategories[INTERESTCATEGORY_MAX];		/**< Mission category that should use this
															 * alien team Category. */
	int numMissionCategories;					/**< Number of category using this alien team Category. */

	linkedList_t* equipment;		/**< Equipment definitions that may be used for this def. */

	alienTeamGroup_t alienTeamGroups[MAX_ALIEN_GROUP_PER_CATEGORY];		/**< Different alien group available
																 * for this category */
	int numAlienTeamGroups;			/**< Number of alien group defined for this category */
} alienTeamCategory_t;

/** @brief mission definition
 * @note A mission is different from a map: a mission is the whole set of actions aliens will carry.
 * For example, coming with a UFO on earth, land, explore earth, and leave with UFO
 */
typedef struct mission_s {
	int idx;						/**< unique id of this mission */
	char id[MAX_VAR];				/**< script id */
	mapDef_t* mapDef;				/**< mapDef used for this mission */
	bool active;					/**< aircraft at place? */
	union missionData_t {
		base_t* base;
		aircraft_t* aircraft;
		installation_t* installation;
		alienBase_t* alienBase;
		city_t* city;
	} data;							/**< may be related to mission type (like pointer to base attacked, or to alien base) */
	interestCategory_t category;	/**< The category of the event */
	missionStage_t stage;			/**< in which stage is this event? */
	int initialOverallInterest;		/**< The overall interest value when this event has been created */
	int initialIndividualInterest;	/**< The individual interest value (of type type) when this event has been created */
	date_t startDate;				/**< Date when the event should start */
	date_t finalDate;				/**< Date when the event should finish (e.g. for aerial recon)
									 * if finaleDate.day == 0, then delay is not a limitating factor for next stage */
	vec2_t pos;						/**< Position of the mission */
	aircraft_t* ufo;				/**< UFO on geoscape fulfilling the mission (may be nullptr) */
	bool onGeoscape;				/**< Should the mission be displayed on geoscape */
	bool crashed;					/**< is UFO crashed ? (only used if mission is spawned from a UFO */

	char onwin[MAX_VAR];			/**< trigger command after you've won a battle, @sa CP_ExecuteMissionTrigger */
	char onlose[MAX_VAR];			/**< trigger command after you've lost a battle, @sa CP_ExecuteMissionTrigger */
	bool posAssigned;				/**< is the position of this mission already set? */
} mission_t;

/**
 * @brief iterates through missions
 */
#define MIS_Foreach(var) LIST_Foreach(ccs.missions, mission_t, var)

/** battlescape parameters that were used */
typedef struct battleParam_s {
	mission_t* mission;
	alienTeamGroup_t* alienTeamGroup;	/**< Races of aliens present in battle */
	char* param;						/**< in case of a random map assembly we can't use the param from mapDef - because
										 * this is global for the mapDef - but we need a local mission param */
	char alienEquipment[MAX_VAR];		/**< Equipment of alien team */
	char civTeam[MAX_VAR];				/**< Type of civilian (European, ...) */
	bool day;							/**< Mission is played during day */
	const char* zoneType;				/**< Terrain type (used for texture replacement in some missions (base, ufocrash)) */
	int aliens, civilians;				/**< number of aliens and civilians in that particular mission */
	struct nation_s* nation;			/**< nation where the mission takes place */
	bool retriable;						/**< if the battle can be retried */
} battleParam_t;

typedef enum {
	WON, DRAW, LOST
} missionState_t;

/** @brief Structure with mission info needed to create results summary at menu won. */
typedef struct missionResults_s {
	const mission_t* mission;
	missionState_t state;
	bool recovery;		/**< @c true if player secured a UFO (landed or crashed). */
	bool crashsite;		/**< @c true if secured UFO was crashed one. */
	ufoType_t ufotype;		/**< Type of UFO secured during the mission. */
	float ufoCondition;		/**< How much the UFO is damaged */
	int itemTypes;			/**< Types of items gathered from a mission. */
	int itemAmount;			/**< Amount of items (all) gathered from a mission. */
	int aliensKilled;
	int aliensStunned;
	int aliensSurvived;
	int ownKilled;
	int ownStunned;
	int ownKilledFriendlyFire;
	int ownSurvived;
	int civiliansKilled;
	int civiliansKilledFriendlyFire;
	int civiliansSurvived;
} missionResults_t;

/** salary values for a campaign */
typedef struct salary_s {
	int base[MAX_EMPL];
	int rankBonus[MAX_EMPL];
	int admin[MAX_EMPL];
	int aircraftFactor;
	int aircraftDivisor;
	int baseUpkeep;
	int adminInitial;
	float debtInterest;
} salary_t;

/** campaign definition */
typedef struct campaign_s {
	int idx;					/**< own index in global campaign array */
	char id[MAX_VAR];			/**< id of the campaign */
	char name[MAX_VAR];			/**< name of the campaign */
	int team;					/**< what team can play this campaign */
	char researched[MAX_VAR];	/**< name of the researched tech list to use on campaign start */
	char soldierEquipment[MAX_VAR];	/**< name of the equipment list that is used to equip soldiers on crafts that are added to the first base */
	char equipment[MAX_VAR];	/**< name of the equipment list to use on campaign start */
	char market[MAX_VAR];		/**< name of the market list containing initial items on market */
	char asymptoticMarket[MAX_VAR];		/**< name of the market list containing items on market at the end of the game */
	const equipDef_t* marketDef;		/**< market definition for this campaign (how many items on the market) containing initial items */
	const equipDef_t* asymptoticMarketDef;	/**< market definition for this campaign (how many items on the market) containing finale items */
	char text[MAX_VAR];			/**< placeholder for gettext stuff */
	char map[MAX_VAR];			/**< geoscape map */
	int soldiers;				/**< start with x soldiers */
	int scientists;				/**< start with x scientists */
	int workers;				/**< start with x workers */
	int pilots;					/**< start with x pilots */
	int credits;				/**< start with x credits */
	int num;
	signed int difficulty;		/**< difficulty level -4 - 4 */
	float minhappiness;			/**< minimum value of mean happiness before the game is lost */
	int negativeCreditsUntilLost;	/**< bankrupt - negative credits until you've lost the game */
	int maxAllowedXVIRateUntilLost;	/**< 0 - 100 - the average rate of XVI over all nations before you've lost the game */
	bool visible;				/**< visible in campaign menu? */
	date_t date;				/**< starting date for this campaign */
	int basecost;				/**< base building cost for empty base */
	char firstBaseTemplate[MAX_VAR];	/**< template to use for setting up the first base */
	bool finished;
	const campaignEvents_t* events;
	salary_t salaries;
	float produceRate;			/**< higher number = faster production */
	float researchRate;			/**< specifies the number of research hours that a single scientist produces in a single hour of game time */
	float healingRate;			/**< the hospital healing rate */
	float ufoReductionRate;		/**< is used in the equation which spawns UFOs to determine the probability that a UFO will not be spawned.
								 * It works like this: the game says: 10 UFOs can be spawned in this cycle. For each UFO it picks a number between 0.0 and 1.0.
								 * If the number is higher than ufoReductionRate, it is spawned. Otherwise it is not. So higher numbers lead to fewer UFOs. */
	float employeeRate;			/**< Easier difficulties could offer more monthly recruits and harder difficulties less */
	int initialInterest;
	int alienBaseInterest;		/**< the alien interest level at which aliens begin trying to build bases. */
} campaign_t;

int CP_GetSalaryBaseEmployee(const salary_t* salary, employeeType_t type);
int CP_GetSalaryAdminEmployee(const salary_t* salary, employeeType_t type);
int CP_GetSalaryRankBonusEmployee(const salary_t* salary, employeeType_t type);
int CP_GetSalaryAdministrative(const salary_t* salary);
int CP_GetSalaryUpKeepBase(const salary_t* salary, const base_t* base);

/** possible geoscape actions */
typedef enum mapAction_s {
	MA_NONE,
	MA_NEWBASE,				/**< build a new base */
	MA_NEWINSTALLATION,		/**< build a new installation */
	MA_INTERCEPT,			/**< intercept */
	MA_BASEATTACK,			/**< base attacking */
	MA_UFORADAR				/**< ufos are in our radar */
} mapAction_t;

typedef void (*missionSpawnFunction_t) (void);
typedef void (*missionResultFunction_t) (const missionResults_t* results);

/**
 * @brief client campaign structure
 * @sa csi_t
 */
typedef struct ccs_s {
	equipDef_t eMission;					/**< this is a copy of the base storage we are starting a mission from. This is needed because
											 * we don't want to "waste" items on a retry. */
	market_t eMarket;						/**< Prices, evolution and number of items on market */

	linkedList_t* missions;					/**< Missions spawned (visible on geoscape or not) */

	battleParam_t battleParameters;			/**< Structure used to remember every parameter used during last battle */

	int lastInterestIncreaseDelay;				/**< How many hours since last increase of alien overall interest */
	int overallInterest;						/**< overall interest of aliens: how far is the player in the campaign */
	int interest[INTERESTCATEGORY_MAX];			/**< interest of aliens: determine which actions aliens will undertake */
	int lastMissionSpawnedDelay;				/**< How many days since last mission has been spawned */

	int credits;			/**< actual credits amount */
	int civiliansKilled;	/**< how many civilians were killed already */
	int aliensKilled;		/**< how many aliens were killed already */
	date_t date;			/**< current date */
	bool startXVI;			/**< the aliens are starting to spread XVI */
	float timer;
	float frametime;

	struct {
		mission_t* selectedMission;			/**< Currently selected mission on geoscape */
		aircraft_t* selectedAircraft;		/**< Currently selected aircraft on geoscape */
		aircraft_t* selectedUFO;			/**< Currently selected UFO on geoscape */
		aircraft_t* interceptAircraft;		/**< selected aircraft for interceptions */
		aircraft_t* missionAircraft;		/**< aircraft pointer for mission handling */
	} geoscape;

	/* == misc == */
	/* MA_NEWBASE, MA_INTERCEPT, MA_BASEATTACK, ... */
	mapAction_t mapAction;

	/** @todo move into the base node extra data */
	/* BA_NEWBUILDING ... */
	baseAction_t baseAction;

	/* how fast the game is running */
	int gameTimeScale;
	int gameLapse;

	/* already paid in this month? */
	bool paid;

	/** Coordinates to place the new base at (long, lat) */
	vec2_t newBasePos;

	/* == employees == */
	/* A list of all phalanx employees (soldiers, scientists, workers, etc...) */
	linkedList_t* employees[MAX_EMPL];

	/* == technologies == */
	/* A list of all research-topics resp. the research-tree. */
	technology_t technologies[MAX_TECHNOLOGIES];
	/* Total number of technologies. */
	int numTechnologies;

	/* == bases == */
	/* A list of _all_ bases ... even unbuilt ones. */
	base_t bases[MAX_BASES];
	/* Total number of built bases (how many are enabled). */
	int numBases;

	/* a list of all templates for building bases */
	baseTemplate_t baseTemplates[MAX_BASETEMPLATES];
	int numBaseTemplates;

	/* == aircraft == */
	linkedList_t* aircraft;

	/* == Alien bases == */
	linkedList_t* alienBases;

	/* == Nations == */
	nation_t nations[MAX_NATIONS];
	int numNations;

	/* == Cities == */
	linkedList_t* cities;
	int numCities;

	/* Projectiles on geoscape (during fights) */
	aircraftProjectile_t projectiles[MAX_PROJECTILESONGEOSCAPE];
	int numProjectiles;

	/* == Transfers == */
	linkedList_t* transfers;

	/* UFO components. */
	int numComponents;
	components_t components[MAX_ASSEMBLIES];

	/* == stored UFOs == */
	linkedList_t* storedUFOs;

	/* Alien Team Package used during battle */
	alienTeamCategory_t alienCategories[ALIENCATEGORY_MAX];	/**< different alien team available
														 * that will be used in mission */
	int numAlienCategories;		/** number of alien team categories defined */

	/* == ufopedia == */
	/* A list of all UFOpaedia chapters. */
	pediaChapter_t upChapters[MAX_PEDIACHAPTERS];
	/* Total number of UFOpaedia chapters */
	int numChapters;
	int numUnreadMails; /**< only for faster access (don't cycle all techs every frame) */

	eventMail_t eventMails[MAX_EVENTMAILS];	/**< holds all event mails (cl_event.c) */
	int numEventMails;	/**< how many eventmails (script-id: mail) parsed */

	campaignEvents_t campaignEvents[MAX_CAMPAIGNS];	/**< holds all campaign events (cl_event.c) */
	int numCampaignEventDefinitions;	/**< how many event definitions (script-id: events) parsed */

	campaignTriggerEvent_t campaignTriggerEvents[MAX_CAMPAIGN_TRIGGER_EVENTS];
	int numCampaignTriggerEvents;

	/* == buildings in bases == */
	/* A list of all possible unique buildings. */
	building_t buildingTemplates[MAX_BUILDINGS];
	int numBuildingTemplates;
	/*  A list of the building-list per base. (new buildings in a base get copied from buildingTypes) */
	building_t buildings[MAX_BASES][MAX_BUILDINGS];
	/* Total number of buildings per base. */
	int numBuildings[MAX_BASES];

	/* == installations == */
	/* A template for each possible installation with configurable values */
	installationTemplate_t installationTemplates[MAX_INSTALLATION_TEMPLATES];
	int numInstallationTemplates;

	/* A list of _all_ installations */
	linkedList_t* installations;

	/* UFOs on geoscape */
	aircraft_t ufos[MAX_UFOONGEOSCAPE];
	int numUFOs;	/**< The current amount of UFOS on the geoscape. */

	/* message categories */
	msgCategory_t messageCategories[MAX_MESSAGECATEGORIES];
	int numMsgCategories;

	/* entries for message categories */
	msgCategoryEntry_t msgCategoryEntries[NT_NUM_NOTIFYTYPE + MAX_MESSAGECATEGORIES];
	int numMsgCategoryEntries;

	/* == Ranks == */
	/* Global list of all ranks defined in medals.ufo. */
	rank_t ranks[MAX_RANKS];
	/* The number of entries in the list above. */
	int numRanks;

	/* cache for techdef technologies */
	technology_t* teamDefTechs[MAX_TEAMDEFS];

	/* cache for item technologies */
	technology_t* objDefTechs[MAX_OBJDEFS];

	campaign_t* curCampaign;			/**< Current running campaign */
	stats_t campaignStats;
	missionResults_t missionResults;

	campaign_t campaigns[MAX_CAMPAIGNS];
	int numCampaigns;

	aircraft_t aircraftTemplates[MAX_AIRCRAFT];		/**< Available aircraft types/templates/samples. */
	int numAircraftTemplates;		/**< Number of aircraft templates. */

	missionSpawnFunction_t missionSpawnCallback;
	missionResultFunction_t missionResultCallback;

	linkedList_t* updateCharacters;
} ccs_t;

typedef struct {
	int x, y;
} screenPoint_t;

extern ccs_t ccs;
extern const int DETECTION_INTERVAL;
extern cvar_t* cp_campaign;
extern cvar_t* cp_missiontest;
extern cvar_t* cp_start_employees;

#define MAX_CREDITS 10000000

#include "../cgame.h"
extern const cgame_import_t* cgi;

/* Campaign functions */
void CP_InitStartup(void);
campaign_t* CP_GetCampaign(const char* name);
void CP_CampaignInit(campaign_t* campaign, bool load);
void CP_ParseCampaignData(void);
void CP_ReadCampaignData(const campaign_t* campaign);
bool CP_IsRunning(void);

void CP_CampaignRun(campaign_t* campaign, float secondsSinceLastFrame);
void CP_CheckLostCondition(const campaign_t* campaign);
void CP_EndCampaign(bool won);

void CP_Shutdown(void);
void CP_ResetCampaignData(void);

/* Mission related functions */
int CP_CountMissionOnGeoscape(void);
void CP_UpdateMissionVisibleOnGeoscape(void);
int CP_TerrorMissionAvailableUFOs(const mission_t* mission, ufoType_t* ufoTypes);
bool AIR_SendAircraftToMission(aircraft_t* aircraft, mission_t* mission);
void AIR_AircraftsNotifyMissionRemoved(const mission_t* mission);

void CP_UFOProceedMission(const campaign_t* campaign, aircraft_t* ufocraft);
mission_t* CP_CreateNewMission(interestCategory_t category, bool beginNow);
bool CP_ChooseMap(mission_t* mission, const vec2_t pos);
void CP_StartSelectedMission(void);

void CP_HandleNationData(float minHappiness, mission_t* mis, const nation_t* nation, const missionResults_t* results);
void CP_UpdateCharacterStats(const base_t* base, const aircraft_t* aircraft);

/* Credits management */
bool CP_CheckCredits (int costs);
void CP_UpdateCredits(int credits);

/* Other functions */
int CP_CharacterGetMaxExperiencePerMission(const abilityskills_t skill);
void CP_UpdateCharacterSkills(character_t* chr);
void CP_UpdateCharacterData(linkedList_t* updateCharacters);
void CP_ParseCharacterData(dbuffer* msg, linkedList_t** updateCharacters);
bool CP_CheckNextStageDestination(const campaign_t* campaign, aircraft_t* ufo);

aircraft_t* AIR_NewAircraft(base_t* base, const aircraft_t* aircraftTemplate);

void CP_GetRandomPosOnGeoscape(vec2_t pos, bool noWater);
bool CP_GetRandomPosOnGeoscapeWithParameters(vec2_t pos, const linkedList_t* terrainTypes, const linkedList_t* cultureTypes, const linkedList_t* populationTypes, const linkedList_t* nations);

void CP_GameAutoGo(mission_t* mission, aircraft_t* aircraft, const campaign_t* campaign, const battleParam_t* battleParameters, missionResults_t* results);

bool CP_OnGeoscape(void);
