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

#define outfit_isProp(o,p)  ((o)->properties & p)
/* Property flags. */
#define OUTFIT_PROP_WEAP_SECONDARY (1<<0)

/* Outfit types. */
typedef enum OutfitType_ {
  OUTFIT_TYPE_NULL,
  OUTFIT_TYPE_BOLT,
  OUTFIT_TYPE_BEAM,
  OUTFIT_TYPE_TURRET_BOLT,
  OUTFIT_TYPE_TURRET_BEAM,
  OUTFIT_TYPE_MISSILE_DUMB,
  OUTFIT_TYPE_MISSILE_DUMB_AMMO,
  OUTFIT_TYPE_MISSILE_SEEK,
  OUTFIT_TYPE_MISSILE_SEEK_AMMO,
  OUTFIT_TYPE_MISSILE_SEEK_SMART,
  OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO,
  OUTFIT_TYPE_MISSILE_SWARM,
  OUTFIT_TYPE_MISSILE_SWARM_AMMO,
  OUTFIT_TYPE_MISSILE_SWARM_SMART,
  OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO,
  OUTFIT_TYPE_MODIFICATION,
  OUTFIT_TYPE_AFTERBURNER,
  OUTFIT_TYPE_MAP,
  OUTFIT_TYPE_JAMMER,
  OUTFIT_TYPE_SENTINEL  /* Indicates last type. */
} OutfitType;

typedef enum DamageType_ {
  DAMAGE_TYPE_NULL,
  DAMAGE_TYPE_ENERGY,
  DAMAGE_TYPE_KINETIC,
  DAMAGE_TYPE_ION,
  DAMAGE_TYPE_RADIATION
} DamageType;

/* An outfit depends a lot on the type. */
typedef struct Outfit_ {
  char* name;

  /* General specs. */
  int max;
  int tech;
  int mass;

  /* Store stuff. */
  unsigned int price;
  char* description;

  glTexture* gfx_store; /* Store graphic. */

  int properties; /* Properties stored bitwise. */

  /* Type dependant. */
  OutfitType type;
  union {
    struct { /* Bolt. */
      unsigned int delay; /* Delay between shots. */
      double speed;       /* Speed of shot. (not applicable to beam. */
      double range;
      double accuracy;    /* Desviation accuracy. */
      double energy;      /* Energy usage. */
      DamageType dtype;   /* Damage type. */
      double damage;      /* Damage. */

      glTexture* gfx_space;
      int sound;          /* Sound to play. */
      int spfx;           /* Special effect on hit. */
    } blt;
    struct { /* Beam. */
      double range;     /* Distance it travels. */
      glColour colour;  /* Beam colour. */
      double energy;    /* Energy drained. */
      double damage_armour, damage_shield; /* Damage. */
    } bem;
    struct { /* Launcher. */
      unsigned int delay; /* Delay between shots. */
      char* ammo;
    } lau;
    struct { /* Ammo. */
      double duration;        /* Duration. */
      double lockon;          /* Time it takes to lock on the target. */
      double resist;          /* Lowers chance of jamming by this ammount. */

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

      glTexture* gfx_space;
      int sound;              /* Sound to play. */
      int spfx;               /* Special effect on hit. */
    } amm;
    struct { /* Modification. */
      /* Movement. */
      double thrust, turn, speed;

      /* Health. */
      double armour, armour_regen;
      double shield, shield_regen;
      double energy, energy_regen;
      double fuel;

      /* Misc. */
      int cargo; /* Cargo space to add. */
    } mod;
    struct { /* Afterburner. */
      double rumble;                    /* Percent of rumble. */
      int sound;                        /* Sound of the afterburner. */
      double thrust_perc, thrust_abs;   /* Percent and absolute thrust bonus. */
      double speed_perc, speed_abs;     /* Percent and absolute speed bonus. */
      double energy;                    /* Energy used while active. */
    } afb;
    struct { /* Map. */
      double radius;                    /* Amount of systems to add */
    } map;
    struct {
      double range;                     /* Range it starts to do effect. */
      double chance;                    /* Chance of it nullifying the missile. */
      double energy;                    /* Energy it uses to run. */
    } jam;
  } u;
} Outfit;

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

/* Get. */
Outfit* outfit_get(const char* name);
char** outfit_getTech(int* n, const int* tech, const int techmax);
/* Outfit types. */
int outfit_isWeapon(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);

