#pragma once
#include "opengl.h"
#include "sound.h"

#define outfit_isProp(o,p)  ((o)->properties & p) /**< Check an outfit for property. */
/* Property flags. */
#define OUTFIT_PROP_WEAP_SECONDARY (1<<0) /**< Is a secondary weapon? */

/**
 * @enum OutfitType
 *
 * @brief Different types of existing outfits.
 *
 * Outfits are organized by the order here.
 */
typedef enum OutfitType_ {
  OUTFIT_TYPE_NULL,                       /**< NULL type. */
  OUTFIT_TYPE_BOLT,                       /**< @todo Fixed bolt cannon. */
  OUTFIT_TYPE_BEAM,                       /**< Fixed beam cannon. */
  OUTFIT_TYPE_TURRET_BOLT,                /**< @todo Rotaty bolt turret. */
  OUTFIT_TYPE_TURRET_BEAM,                /**< Rotary bolt turret. */
  OUTFIT_TYPE_MISSILE_DUMB,               /**< Dumb missile launcher. */
  OUTFIT_TYPE_MISSILE_DUMB_AMMO,          /**< Dumb missile ammo. */
  OUTFIT_TYPE_MISSILE_SEEK,               /**< Seeker missile launcher. */
  OUTFIT_TYPE_MISSILE_SEEK_AMMO,          /**< Seeker missile ammo. */
  OUTFIT_TYPE_MISSILE_SEEK_SMART,         /**< ATM equivalent to SEEK. */
  OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO,    /**< @todo atm equivalent to SEEK_AMMI. */
  OUTFIT_TYPE_MISSILE_SWARM,              /**< @todo Swarm missile launcher. */
  OUTFIT_TYPE_MISSILE_SWARM_AMMO,         /**< @todo Swarm missile ammo. */
  OUTFIT_TYPE_MISSILE_SWARM_SMART,        /**< @todo Same as SWARM. */
  OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO,   /**< @todo Same as SWARM_AMMO. */
  OUTFIT_TYPE_MODIFICATION,               /**< Modifies the ship afterburn capability. */
  OUTFIT_TYPE_AFTERBURNER,                /**< Gives the ship afterburn capability. */
  OUTFIT_TYPE_JAMMER,                     /**< Used to nullify seeker missiles. */
  OUTFIT_TYPE_MAP,                        /**< Give the player more knowledge about systems. */
  OUTFIT_TYPE_SENTINEL                    /**< Indicates last type. */
} OutfitType;

/**
 * @enum DamageType
 *
 * @brief Different types of damage.
 */
typedef enum DamageType_ {
  DAMAGE_TYPE_NULL,       /**< NULL. */ 
  DAMAGE_TYPE_ENERGY,     /**< Energy-based weapons. */
  DAMAGE_TYPE_KINETIC,    /**< Physic impact weapons. */
  DAMAGE_TYPE_ION,        /**< Ion-based weapons. */
  DAMAGE_TYPE_RADIATION   /**< Radioactive weapons. */
} DamageType;

/**
 * @struct OutfitBoldData
 *
 * @brief Represents the particular properties of a bolt weapon.
 */
typedef struct OutfitBoltData_ {
  unsigned int delay;   /**< Delay between shots. */
  double speed;         /**< How fast it goes (not applicable to beam). */
  double range;         /**< How far it goes. */
  double accuracy;      /**< Desviation accuracy. */
  double energy;        /**< Energy usage. */
  DamageType dtype;     /**< Damage type. */
  double damage;        /**< damage. */

  /* Sound and graphics. */
  glTexture* gfx_space; /**< Graphic. */
  int sound;            /**< Sound to play. */
  int spfx;             /**< Special effect on hit. */
} OutfitBoltData;

/**
 * @struct OutfitBeamData
 *
 * @brief Represents the particular properties of a beam weapon.
 */
typedef struct OutfitBeamData_ {
  /* Time stuff. */
  unsigned int delay;     /**< Delay between usage. */
  double warmup;          /**< How long it takes to warm up. */
  double duration;        /**< How long the beam lasts active. */

  /* Beam properties. */
  double range;           /**< How far it goes. */
  double turn;            /**< How fast it can turn. Only for turrets. */
  glColour* colour;       /**< Beam colour. */
  double energy;          /**< Amount of energy it drains (per second). */
  DamageType dtype;       /**< Damage type. */
  double damage;          /**< Damage amount. */

  /* Graphics and sound */
  glTexture* gfx;         /**< Base texture. */
  int spfx;               /**< Special effect on hit. */
  int sound_warmup;       /**< Sound to play when warming up. @todo use. */
  int sound;              /**< Sound to play. */
  int sound_off;          /**< Sound to play when turning off. */
} OutfitBeamData;

/**
 * @struct OutfitLauncherData
 *
 * @brief Represents a particular missile launcher.
 *
 * The properties of the weapon are highly dependant on the ammunition.
 */
typedef struct OutfitLauncherData_ {
  unsigned int delay;   /**< Delay between shots. */
  char* ammo;           /**< The ammo to use. */
} OutfitLauncherData;

/**
 * @struct OutfitAmmoData
 *
 * @brief Represents ammunition for a launcher.
 */
typedef struct OutfitAmmoData_ {
  double duration;      /**< How long the ammo lives. */
  double lockon;        /**< Time it takes to lock on the target. */
  double resist;        /**< Lowers chance of jamming by this amount. */

  double speed;         /**< Max speed. */
  double turn;          /**< Turn velocity. */
  double thrust;        /**< Acceleration. */
  double energy;        /**< Energy usage. */
  DamageType dtype;     /**< Damage type. */
  double damage;        /**< Damage. */

  glTexture* gfx_space; /**< Graphic. */
  int sound;            /**< Sound to play. */
  int spfx;             /**< Special effect on hit. */
} OutfitAmmoData;

/**
 * @struct OutfitModificationData
 *
 * @brief Represents a ship modification.
 *
 * These modify the ship's basic properties when equipped on a pilot.
 */
typedef struct OutfitModificationData_ {
  /* Movement. */
  double thrust;          /**< Max thrust modifier. */
  double turn;            /**< Max turn modifier. */
  double speed;           /**< Max speed modifier. */

  /* Health. */
  double armour;          /**< Max armour modifier. */
  double armour_regen;    /**< Armour regeneration modifier. */
  double shield;          /**< Max shield modifier. */
  double shield_regen;    /**< Shield regeneration modifier. */
  double energy;          /**< Max energy modifier. */
  double energy_regen;    /**< Energy regeneration modifier. */
  double fuel;            /**< Max fuel modifier. */

  /* Misc. */
  int cargo;              /**< Cargo space modifier. */
} OutfitModificationData;

/**
 * @struct OutfitAfterburnerData
 *
 * @brief Represents an afterburner.
 */
typedef struct OutfitAfterburnerData_ {
  double rumble;          /**< Percent of rumble. */
  int sound;              /**< Sound of afterburner. */
  double thrust_perc;     /**< Percent of thrust increase based on ship base. */
  double thrust_abs;      /**< Fixed absolute thrust increase. */
  double speed_perc;      /**< Percent of speed to increase based on ship base. */
  double speed_abs;       /**< Fixed absolulte speed increase. */
  double energy;          /**< Energy used while active. */
} OutfitAfterburnerData;

/**
 * @struct OutfitMapData
 *
 * @brief Represents a map, is not actually stored on a ship but put into the
 * nav system.
 *
 * Basically just marks an amount of systems whe the player buys it as known.
 */
typedef struct OutfitMapData_ {
  double radius;        /**< Number of jumps to add all systems within. */
} OutfitMapData;

/**
 * @struct OutfitJammerData
 *
 * @brief Represents a jammer.
 */
typedef struct OutfitJammerData_ {
  double range;       /**< Range it starts to do effect. */
  double chance;      /**< Chance of it nullifying the missile. */
  double energy;      /**< Energy it uses to run. */
} OutfitJammerData;

/**
 * @struct Outfit
 *
 * @brief A ship outfit, depends radically on the type.
 */
typedef struct Outfit_ {
  char* name;               /**< Name of the outfit. */

  /* General specs. */
  int max;                  /**< Max amount one can own. */
  int tech;                 /**< Tech needed to sell it. */
  int mass;                 /**< How much weapon capacity is needed. */

  /* Store stuff. */
  unsigned int price;       /**< Base sell price. */
  char* description;        /**< Store description. */

  glTexture* gfx_store;     /**< Store graphic. */

  int properties;           /**< Properties stored bitwise. */

  /* Type dependant. */
  OutfitType type;          /**< Properties stored bitwise. */
  union {
    OutfitBoltData          blt;  /**< BOLT. */
    OutfitBeamData          bem;  /**< BEAM. */
    OutfitLauncherData      lau;  /**< MISSILE. */
    OutfitAmmoData          amm;  /**< AMMO. */
    OutfitModificationData  mod;  /**< MODIFICATION. */
    OutfitAfterburnerData   afb;  /**< AFTERBURNER. */
    OutfitJammerData        jam;  /**< JAMMER. */
    OutfitMapData           map;  /**< MAP. */
  } u;
} Outfit;

/* Misc. */
void outfit_calcDamage(double* dshield, double* darmour, double* knockback,
    DamageType dtype, double dmg);

/* Get. */
Outfit* outfit_get(const char* name);
Outfit** outfit_getTech(int* n, const int* tech, const int techmax);
/* Outfit types. */
int outfit_isWeapon(const Outfit* o);
int outfit_isBolt(const Outfit* o);
int outfit_isBeam(const Outfit* o);
int outfit_isLauncher(const Outfit* o);
int outfit_isAmmo(const Outfit* o);
int outfit_isTurret(const Outfit* o);
int outfit_isMod(const Outfit* o);
int outfit_isAfterburner(const Outfit* o);
int outfit_isMap(const Outfit* o);
int outfit_isJammer(const Outfit* o);
const char* outfit_getType(const Outfit* o);
const char* outfit_getTypeBroad(const Outfit* o);

/* Get data from outfit. */
glTexture* outfit_gfx(const Outfit* o);
int outfit_spfx(const Outfit* o);
double outfit_damage(const Outfit* o);
DamageType outfit_damageType(const Outfit* o);
int outfit_delay(const Outfit* o);
double outfit_energy(const Outfit* o);
double outfit_range(const Outfit* o);
double outfit_speed(const Outfit* o);
int outfit_isSeeker(const Outfit* o);

/* Load/free outfit stack. */
int outfit_load(void);
void outfit_free(void);

