////////////////////////////////////////////////////////////////////////////////
// MWBase.h
// Copyright Bjoern Ganster
// Developed since 2007
////////////////////////////////////////////////////////////////////////////////

#ifndef MWBase__H
#define MWBase__H

#include "BGBase.h"
#include "MemoryBlock.h"
#include "BGCPString.h"
#include "Mesh.h"
#include "Texture.h"

////////////////////////////////////////////////////////////////////////////////
// File types and names

enum FileType {
	unsupported,
	WAV,
	PCX,
	BMP,
	#ifdef MECHVM
	XEL,
	WTB,
	Mech,
	PRJ,
	SHP,
	SFL,
	COL,
	DLL,
	EFA,
	FORM,
	FNT,
	BWD,
	MW2_DB,
	TEX,
	MW2_555,
	MW3_555,
	SMK,
	ZBD, // MW3 project files
	FLT, // MW3 mech files
	ISO_9660,
	ISO_9660_AUDIO, // an audio track on a CD
	ZFS, // Interstate 76 version of MW2.PRJ
	OBJ, // Wavefront OBJ (3D format)
	MW3GameZMesh, // A mesh as defined in a MW3 gamez.zbd file
	MW3PMGameZMesh, // A mesh as defined in MW3:PM gamez.zbd file
	MW3GameZNodes, // Scene graph stored in a MW3 gamez.zbd file
	MW3PMGameZNodes, // Scene graph stored in a MW3:PM gamez.zbd file
	MW3ZReader, // pseudo-archive to read reader.zbd files
	MW3ZReaderContents, // key-value pairs stored in reader.zbd
	MW4ResourceFile
	#endif
};

FileType getFileTypeFromExtension (const char* FN);
FileType getFileTypeFromExtension (const wchar_t* FileName);
const char* getMWFileExt (FileType FileTypeID);
FileType getFileTypeFromContent (const MemoryBlock* mb);

////////////////////////////////////////////////////////////////////////////////
// Weapon description records

static const size_t MaxAmmoTypes = 20;

const static DWORD MWWeaponFlag_Ammo = 1;
const static DWORD MWWeaponFlag_MWCannotFire = 2;
const static DWORD MWWeaponFlag_IncludeInWeaponList = 4;
const static DWORD MWWeaponFlag_CountedInMEK = 8;
const static DWORD MWweaponFlag_WorksOverWater = 16;
const static DWORD MWweaponFlag_WorksUnderwater = 32;

const int LongWeaponNameLen = 30;
const int ShortWeaponNameLen = 11;

// Combinations of flags above
const static DWORD MWWeaponFlagsStdWeapon = 
   MWWeaponFlag_IncludeInWeaponList | MWWeaponFlag_CountedInMEK | MWweaponFlag_WorksOverWater;
const static DWORD MWWeaponFlagsStdAmmo = 
   MWWeaponFlag_Ammo | MWWeaponFlag_CountedInMEK;

enum WeaponCategory {
	energy,
	missile, 
	bullet
};

struct MWEquipment {
	int Heat; // Heat when fired
	int MaxDamage; // Maximum weapon damage
	int MinimumRangeInMeters; // Minimum range for firing the weapon
	int MaxDamageRange; // Maximum range where the weapon does its full damage
	int MaxRangeInMeters; // The maximum range for the weapon does minimum damage
	int TonnageTimes100; // Weapon weight
	int Criticals; // Number of criticals used by the weapon
	int ShotsPerTon; // If positive, this record describes ammo
	int AvailableInYear; // Year of field/open market availability
	int CBills; // Price in C-Bills
	int AmmoTypes[MaxAmmoTypes]; // Ammo that this weapon can use
	char longName[LongWeaponNameLen], shortName[ShortWeaponNameLen];

	// Weapons that don't exist in MW2 use IDs that start at 20000 and should be marked with the comment "// Not in MW2"
	WORD MW2_31st_ID; // ID's used by MW2:31stcc and GBL, but not Battlepack and Titanium Trilogy. Max value used in MechVM is 23800.
	WORD MW2_ID; // ID's used by MW2:Mercs, BattlePack and Titanium Trilogy. Max value used in MechVM is 23800.
	WORD MaxCount; // Max. number of IDs used. Important for knowing where the range of ID's for a weapon ends.
	int inInventory;
	DWORD flags;
	Color shotColor;
	double fireDuration; // How long the weapon fires after being triggered
	double coolDown; // How long the weapon needs to cool down after being fired
	// Missing: reload time, TechType, BV, shells fired per shot, recoil angle amplitude
	unsigned int ammoUsedPerShot;
	Mesh* geometry; // geometry used to reflect the weapon in the sim or mech lab
	int xreps, yreps; // nuber of times the geometry should be replicated horizontally or vertically in the sim or mech lab, used esp. for missiles
	double weaponScale; // The scale used to display the weapon in the sim or mech lab
	const char* soundWhenFired;
	WeaponCategory category;
	double metersPerSecond; // Speed of a missile or bullet after being fired
	double defyGravityDuration; // How long a missile can withstand gravity

	const char* getLongName() const
	{ return &longName[0]; }
	const char* getShortName() const
	{ return &shortName[0]; }
};

enum WeaponType {
	Unused_Critical_Slot,

	IS_Energy_Weapon_Base,
	IS1_Flamer,
	IS1_Small_Laser,
	IS1_Medium_Laser,
	IS1_Large_Laser,
	IS1_PPC,
	IS2_Small_Pulse_Laser,
	IS2_Medium_Pulse_Laser,
	IS1_Large_Pulse_Laser,
	IS2_ER_PPC,
	IS2_ER_Small_Laser,
	IS2_ER_Medium_Laser,
	IS2_ER_Large_Laser,

	IS_Ballistic_Weapons,
	IS1_Machine_Gun,
	IS1_Machine_Gun_Ammo,

	// Ordering the AC/20 before the AC/2 prevents parsing errors
	IS1_Autocannon_20,
	IS1_Autocannon_10,
	IS1_Autocannon_5,
	IS1_Autocannon_2,
	IS1_Autocannon_Ammo,
	IS2_Anti_Missile_System,
	IS2_Rotary_AC_2,
	IS2_Rotary_AC_5,
	IS2_Gauss,
	IS2_Gauss_Ammo,
	IS2_Ultra_Autocannon_20,
	IS2_Ultra_Autocannon_10,
	IS2_Ultra_Autocannon_5,
	IS2_Ultra_Autocannon_2,
	IS2_LB_X_Autocannon_20,
	IS2_LB_X_Autocannon_10,
	IS2_LB_X_Autocannon_5,
	IS2_LB_X_Autocannon_2,
	IS2_LB_X_Autocannon_Cluster_Ammo,

    IS_Missile_Weapons,
    IS1_SRM_2,
    IS1_SRM_4,
    IS1_SRM_6,
    IS1_LRM_5,
    IS1_LRM_10,
    IS1_LRM_15,
    IS1_LRM_20,
    IS1_SRM_Ammo,
    IS1_SRM_2_Ammo,
    IS1_SRM_4_Ammo,
    IS1_SRM_6_Ammo,
    IS1_LRM_Ammo,
    IS1_LRM_5_Ammo,
    IS1_LRM_10_Ammo,
    IS1_LRM_15_Ammo,
    IS1_LRM_20_Ammo,
    IS2_MRM_10,
    IS2_MRM_20,
    IS2_MRM_30,
    IS2_MRM_40,
    IS2_MRM_Ammo,

    IS2_SRT_2,
    IS2_SRT_4,
    IS2_SRT_6,
    IS2_LRT_5,
    IS2_LRT_10,
    IS2_LRT_15,
    IS2_LRT_20,
    IS2_SRT_Ammo,
    IS2_LRT_Ammo,

    IS2_Streak_SRM_2,
    IS2_Streak_SRM_4,
    IS2_Streak_SRM_6,
    IS2_Streak_SRM_Ammo,
    IS2_NARC,
    IS2_NARC_AMMO,
    IS2_Arrow_IV,
    IS2_Arrow_IV_Ammo,
    IS2_SRM_Ammo_Inferno,
    //IS1_Rocket_Launcher_10,
    //IS1_Rocket_Launcher_15,
    //IS1_Rocket_Launcher_20,

    Common_Equipment,
    CE_Engine,
    CE_Gyro,
    CE_Life_Support,
    CE_Cockpit,
    CE_Sensors,
    CE_Shoulder,
    CE_Upper_Arm_Actuator,
    CE_Lower_Arm_Actuator,
    CE_Hand,
    CE_Hip,
    CE_Upper_Leg_Actuator,
    CE_Lower_Leg_Actuator,
    CE_Foot,
    CE_Jump_Jet,

    IS_Equipment,
    IS_Heat_Sink,
    IS_Double_Heat_Sink,
    IS_CASE,
    IS_Ferro_Fibrous,
    IS_Endo_Steel,
    IS_Beagle,
    IS_MASC,
    IS_Targeting_Computer,
    IS_TAG,
    IS_Hatchet,
    IS_Sword,

    // Additional Inner Sphere weapons
    CE_Artemis_IV, // Artemis works the same for IS and Clan

    //clanFactor = 10; // Price difference factor to IS
    Clan_Energy_Weapon_Base,
    Clan_ER_Large_Laser,
    Clan_ER_Medium_Laser,
    Clan_ER_Small_Laser,
    Clan_ER_Micro_Laser,
    Clan_Large_Heavy_Laser,
    Clan_Medium_Heavy_Laser,
    Clan_Small_Heavy_Laser,
    Clan_Flamer,
    Clan_ER_PPC,
    Clan_Large_Pulse_Laser,
    Clan_Medium_Pulse_Laser,
    Clan_Small_Pulse_Laser,
    Clan_Micro_Pulse_Laser,

    Clan_Ballistic_Weapons,
    Clan_Anti_Missile_System,
    Clan_Gauss,
    Clan_LB_20_X_AC,
    Clan_LB_10_X_AC,
    Clan_LB_5_X_AC,
    Clan_LB_2_X_AC,
    Clan_Light_Machine_Gun,
    Clan_Machine_Gun,
    Clan_Heavy_Machine_Gun,
    Clan_UAC_20,
    Clan_UAC_10,
    Clan_UAC_5,
    Clan_UAC_2,
    Clan_Autocannon_Ammo,
    Clan_UAC_20_Ammo,
    Clan_UAC_10_Ammo,
    Clan_UAC_5_Ammo,
    Clan_UAC_2_Ammo,
    Clan_LB_X_Ammo,
    Clan_LB_20_X_AC_Ammo,
    Clan_LB_10_X_AC_Ammo,
    Clan_LB_5_X_AC_Ammo,
    Clan_LB_2_X_AC_Ammo,
    Clan_Machine_Gun_Ammo,
    Clan_Gauss_Ammo,
    Clan_Anti_Missile_System_Ammo,

    Clan_Missile_Weapons,
    Clan_ATM_3,
    Clan_ATM_6,
    Clan_ATM_9,
    Clan_ATM_12,
    Clan_ATM_Std_Ammo,
    Clan_ATM_ER_Ammo,
    Clan_ATM_HE_Ammo,
    Clan_SRM_2,
    Clan_SRM_4,
    Clan_SRM_6,
    Clan_SRM_2_Inferno,
    Clan_LRM_5,
    Clan_LRM_10,
    Clan_LRM_15,
    Clan_LRM_20,
    Clan_SRM_Ammo,
    Clan_SRM_2_Ammo,
    Clan_SRM_4_Ammo,
    Clan_SRM_6_Ammo,
    Clan_LRM_Ammo,
    Clan_LRM_5_Ammo,
    Clan_LRM_10_Ammo,
    Clan_LRM_15_Ammo,
    Clan_LRM_20_Ammo,
    Clan_SRM_Ammo_Inferno,
    Clan_NARC_Missile_Beacon,
    Clan_NARC_Missile_Beacon_Ammo,
    Clan_Streak_SRM_2,
    Clan_Streak_SRM_4,
    Clan_Streak_SRM_6,
    Clan_Streak_SRM_2_Inferno,
    Clan_SSRM_Ammo,
    Clan_SSRM_Inferno_Ammo,
    Clan_Streak_SRM_2_Ammo,
    Clan_Streak_SRM_4_Ammo,
    Clan_Streak_SRM_6_Ammo,
    Clan_Arrow_IV,
    Clan_Arrow_IV_Ammo,
    Clan_Nuke,

	Clan_SRT_2,
	Clan_SRT_4,
	Clan_SRT_6,
	Clan_LRT_5,
	Clan_LRT_10,
	Clan_LRT_15,
	Clan_LRT_20,
	Clan_SRT_Ammo,
	Clan_LRT_Ammo,

	Clan_Equipment,
	Clan_Double_Heat_Sink,
	Clan_Targeting_Computer,
	Clan_Ferro_Fibrous,
	Clan_Endo_Steel_Internals,
	Clan_MASC,

	// Add new weapons here (may break compatibility with existing MEK addendums otherweise - heat sink type)
	IS1_Long_Tom,
	IS1_Long_Tom_Ammo,
	IS1_Avionics,
	IS1_Gear,
	IS1_Fuel, // fuel used by internal combustion engines
	IS3_X_Pulse_Laser_Large,
	IS3_X_Pulse_Laser_Medium,
	IS3_X_Pulse_Laser_Small,
	IS2_Light_Gauss,
	IS2_Light_Gauss_Ammo,
	IS2_Heavy_Gauss,
	IS2_Heavy_Gauss_Ammo,
	IS2_Light_Machine_Gun,
	IS2_Heavy_Machine_Gun,
	IS2_Heavy_Machine_Gun_Ammo,
	Clan_Heavy_Machine_Gun_Ammo,
	IS3_Thunderbolt_5,
	IS3_Thunderbolt_10,
	IS3_Thunderbolt_15,
	IS3_Thunderbolt_20,
	IS3_Thunderbolt_Ammo,

	// Stuff to add: Snubnose PPC (3037), MML (3067), Rotary ACs (3062), Heavy PPC (3067), Plasma Rifle (3068), Plasma Cannon (3069), 
	// Rocket Launcher (3064)
	CE_BOMB_100 // simple bomb that causes 100 points of damage with a radius of 60 m
};

static const int WeaponsCount = CE_BOMB_100+1;

// Price factor for clan weapons
static const double clanFactor = 10.0;

// Initialize MW weapons list
void fillWeaponsList();

// Get statistics for a specific weapon
const MWEquipment* getWeaponStats (WeaponType weaponType);
double getEngineWeight (unsigned int engineRating, int EngineType);
bool weaponUsesAmmo (const MWEquipment* w);

bool ammoCompatible(WeaponType weaponType, WeaponType ammoType);

////////////////////////////////////////////////////////////////////////////////
// Mech weapon and equipment defines

const int Tech_Type_Common = 0;
const int Tech_Type_IS_Level_1 = 1;
const int Tech_Type_IS_Level_2 = 2;
const int Tech_Type_Clan = 3;

// Engine types. See Maximum Tech, p.58. Not all of these engine types exist
// in the TechManual, see p. 215
static const int ENGINE_TYPE_STD = 0;
static const int ENGINE_TYPE_LARGE = 1;
static const int ENGINE_TYPE_XL = 2;
static const int ENGINE_TYPE_XXL = 3;
static const int ENGINE_TYPE_LXL = 4;
static const int ENGINE_TYPE_LXXL = 5;
static const int ENGINE_TYPE_COMPACT = 6;

// The heat sinks are in the weapons list ...
//static const int HEAT_SINK_TYPE_SINGLE = 0;
//static const int HEAT_SINK_TYPE_DOUBLE = 1;
//static const int HEAT_SINK_TYPE_COMPACT = 2; // Max. Tech, p. 80
//static const int HEAT_SINK_TYPE_LASER = 3; // Max. Tech, p.80, too strange?

// Maximum Tech offers additional armor types, p. 72
static const int ARMOR_TYPE_STD = 0;
static const int ARMOR_TYPE_LIGHT_FERRO_FIBROUS = 1;
static const int ARMOR_TYPE_FERRO_FIBROUS = 2;
static const int ARMOR_TYPE_HEAVY_FERRO_FIBROUS = 3;
static const int ARMOR_TYPE_STEALTH = 4;

static const int COCKPIT_TYPE_STD = 0;
static const int COCKPIT_TYPE_SMALL = 1;

// Export weapon list as TSV file
void exportWeaponsListAsTSV(const PathChar* fn);

////////////////////////////////////////////////////////////////////////////////
// Common functions

BGCPString getDosBoxPath();

// Add or subtract 360 degrees from v2 to put v2 in the range of v1 ... v3
// todo: rephrase this without a while loop?
template <typename T>
T fixAngle(T v1, T v2, T v3)
{
	while (v2 < v1) {
		v2 += 360.0;
	}
	while (v2 > v3) {
		v2 -= 360.0;
	}
	return v2;
}

#endif
