/*
	This file is part of Warzone 2100.
	Copyright (C) 1999-2004  Eidos Interactive
	Copyright (C) 2005-2020  Warzone 2100 Project

	Warzone 2100 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.

	Warzone 2100 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 Warzone 2100; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @file
 *  Interface to the common stats module
 */
#ifndef __INCLUDED_SRC_STATS_H__
#define __INCLUDED_SRC_STATS_H__

#include "lib/framework/wzconfig.h"

#include <utility>
#include <vector>

#include "objectdef.h"

/**************************************************************************************
 *
 * Function prototypes and data storage for the stats
 */

/* The stores for the different stats */
extern std::vector<BODY_STATS> asBodyStats;
extern std::vector<BRAIN_STATS> asBrainStats;
extern std::vector<PROPULSION_STATS> asPropulsionStats;
extern std::vector<SENSOR_STATS> asSensorStats;
extern std::vector<ECM_STATS> asECMStats;
extern std::vector<REPAIR_STATS> asRepairStats;
extern std::vector<WEAPON_STATS> asWeaponStats;
extern std::vector<CONSTRUCT_STATS> asConstructStats;
extern std::vector<PROPULSION_TYPES> asPropulsionTypes;

//used to hold the modifiers cross refd by weapon effect and propulsion type
extern WEAPON_MODIFIER		asWeaponModifier[WE_NUMEFFECTS][PROPULSION_TYPE_NUM];
extern WEAPON_MODIFIER		asWeaponModifierBody[WE_NUMEFFECTS][SIZE_NUM];

//stores for each players component states - see below
extern UBYTE		*apCompLists[MAX_PLAYERS][COMP_NUMCOMPONENTS];

//store for each players Structure states
extern UBYTE		*apStructTypeLists[MAX_PLAYERS];

//Values to fill apCompLists and apStructTypeLists. Not a bitfield, values are in case that helps with savegame compatibility.
enum ItemAvailability
{
	AVAILABLE = 1,              // This item can be used to design droids.
	UNAVAILABLE = 2,            // The player does not know about this item.
	FOUND = 4,                  // This item has been found, but is unresearched.
	REDUNDANT = 10,             // The player no longer needs this item.
	REDUNDANT_UNAVAILABLE = 11, // The player no longer needs this item.
	REDUNDANT_FOUND = 12,       // The player no longer needs this item.
};

/*******************************************************************************
*		Allocate stats functions
*******************************************************************************/
/* Allocate Weapon stats */
bool statsAllocWeapons(UDWORD numEntries);

/*Allocate Body stats*/
bool statsAllocBody(UDWORD numEntries);

/*Allocate Brain stats*/
bool statsAllocBrain(UDWORD numEntries);

/*Allocate Propulsion stats*/
bool statsAllocPropulsion(UDWORD numEntries);

/*Allocate Sensor stats*/
bool statsAllocSensor(UDWORD numEntries);

/*Allocate Ecm Stats*/
bool statsAllocECM(UDWORD numEntries);

/*Allocate Repair Stats*/
bool statsAllocRepair(UDWORD numEntries);

/*Allocate Construct Stats*/
bool statsAllocConstruct(UDWORD numEntries);

/*******************************************************************************
*		Load stats functions
*******************************************************************************/
// Used from structure.cpp
void loadStructureStats_BaseStats(WzConfig &json, STRUCTURE_STATS *psStats, size_t index);
void unloadStructureStats_BaseStats(const STRUCTURE_STATS &psStats);

/*Load the weapon stats from the file exported from Access*/
bool loadWeaponStats(WzConfig &ini);

/*Load the body stats from the file exported from Access*/
bool loadBodyStats(WzConfig &ini);

/*Load the brain stats from the file exported from Access*/
bool loadBrainStats(WzConfig &ini);

/*Load the propulsion stats from the file exported from Access*/
bool loadPropulsionStats(WzConfig &ini);

/*Load the sensor stats from the file exported from Access*/
bool loadSensorStats(WzConfig &ini);

/*Load the ecm stats from the file exported from Access*/
bool loadECMStats(WzConfig &ini);

/*Load the repair stats from the file exported from Access*/
bool loadRepairStats(WzConfig &ini);

/*Load the construct stats from the file exported from Access*/
bool loadConstructStats(WzConfig &ini);

/*Load the Propulsion Types from the file exported from Access*/
bool loadPropulsionTypes(WzConfig &ini);

/*Load the propulsion sounds from the file exported from Access*/
bool loadPropulsionSounds(const char *pFileName);

/*Load the Terrain Table from the file exported from Access*/
bool loadTerrainTable(WzConfig &ini);

/*Load the Weapon Effect Modifiers from the file exported from Access*/
bool loadWeaponModifiers(WzConfig &ini);

/*******************************************************************************
*		Generic stats functions
*******************************************************************************/

/*calls the STATS_DEALLOC macro for each set of stats*/
bool statsShutDown();

size_t getStatModelLoadingFailures();

UDWORD getSpeedFactor(UDWORD terrainType, UDWORD propulsionType);

/// Get the component index for a component based on the name, verifying with type.
/// It is currently identical to getCompFromID, but may not be in the future.
int getCompFromName(COMPONENT_TYPE compType, const WzString &name);

/// This function only allows you to use the old, deprecated ID name.
int getCompFromID(COMPONENT_TYPE compType, const WzString &name);

/// Get the component pointer for a component based on the name
COMPONENT_STATS *getCompStatsFromName(const WzString &name);

/// Get the structure pointer for a structure based on the name
STRUCTURE_STATS *getStructStatsFromName(const WzString &name);

/// Get the base stat pointer for a stat based on the name
BASE_STATS *getBaseStatsFromName(const WzString &name);

/*returns the weapon sub class based on the string name passed in */
bool getWeaponSubClass(const char *subClass, WEAPON_SUBCLASS *wclass);
const char *getWeaponSubClass(WEAPON_SUBCLASS wclass);

/* returns the translated weapon sub class name - for local display purposes only */
const char *getWeaponSubClassDisplayName(WEAPON_SUBCLASS wclass, bool shortForm);

namespace gfx_api
{
	struct texture; // forward-declare
}
gfx_api::texture* loadImageForWeapSubclass(WEAPON_SUBCLASS subClass);

/*sets the store to the body size based on the name passed in - returns false
if doesn't compare with any*/
bool getBodySize(const WzString &size, BODY_SIZE *pStore);

/**
 * Determines the propulsion type indicated by the @c typeName string passed
 * in.
 *
 * @param typeName  name of the propulsion type to determine the enumerated
 *                  constant for.
 * @param[out] type Will contain an enumerated constant representing the given
 *                  propulsion type, if successful (as indicated by the return
 *                  value).
 *
 * @return true if successful, false otherwise. If successful, @c *type will
 *         contain a valid propulsion type enumerator, otherwise its value will
 *         be left unchanged.
 */
bool getPropulsionType(const char *typeName, PROPULSION_TYPE *type);

/**
 * Determines the weapon effect indicated by the @c weaponEffect string passed
 * in.
 *
 * @param weaponEffect name of the weapon effect to determine the enumerated
 *                     constant for.
 * @param[out] effect  Will contain an enumerated constant representing the
 *                     given weapon effect, if successful (as indicated by the
 *                     return value).
 *
 * @return true if successful, false otherwise. If successful, @c *effect will
 *         contain a valid weapon effect enumerator, otherwise its value will
 *         be left unchanged.
 */
extern const StringToEnumMap<WEAPON_EFFECT> map_WEAPON_EFFECT;

WZ_DECL_PURE int weaponROF(const WEAPON_STATS& psStat, int player);
WZ_DECL_PURE int weaponFirePause(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int weaponReloadTime(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int weaponShortHit(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int weaponLongHit(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int weaponDamage(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int weaponRadDamage(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int weaponPeriodicalDamage(const WEAPON_STATS& psStats, int player);
WZ_DECL_PURE int sensorRange(const SENSOR_STATS& psStats, int player);
WZ_DECL_PURE int ecmRange(const ECM_STATS& psStats, int player);
WZ_DECL_PURE int repairPoints(const REPAIR_STATS& psStats, int player);
WZ_DECL_PURE int constructorPoints(const CONSTRUCT_STATS& psStats, int player);
WZ_DECL_PURE int bodyPower(const BODY_STATS& psStats, int player);
WZ_DECL_PURE int bodyArmour(const BODY_STATS& psStats, int player, WEAPON_CLASS weaponClass);

WZ_DECL_PURE bool objHasWeapon(const BASE_OBJECT *psObj);

bool getWeaponEffect(const WzString& weaponEffect, WEAPON_EFFECT *effect);
/*returns the weapon effect string based on the enum passed in */
const char *getWeaponEffect(WEAPON_EFFECT effect);

bool getWeaponClass(const WzString& weaponClassStr, WEAPON_CLASS *weaponClass);

/* Wrappers */

/** If object is an active radar (has sensor turret), then return a pointer to its sensor stats. If not, return NULL. */
WZ_DECL_PURE SENSOR_STATS *objActiveRadar(const BASE_OBJECT *psObj);

/** Returns whether object has a radar detector sensor. */
WZ_DECL_PURE bool objRadarDetector(const BASE_OBJECT *psObj);

#endif // __INCLUDED_SRC_STATS_H__
