#pragma once

#include <inttypes.h>

#include <phosg/Tools.hh>

#include "StaticGameData.hh"
#include "Types.hh"

enum class EnemyType {
  UNKNOWN = -1,
  NONE = 0,
  NON_ENEMY_NPC,
  AL_RAPPY,
  ASTARK,
  BA_BOOTA,
  BARBA_RAY,
  BARBAROUS_WOLF,
  BEE_L,
  BEE_R,
  BOOMA,
  BOOTA,
  BULCLAW,
  BULK,
  CANADINE,
  CANADINE_GROUP,
  CANANE,
  CHAOS_BRINGER,
  CHAOS_SORCERER,
  CLAW,
  DARK_BELRA,
  DARK_FALZ_1,
  DARK_FALZ_2,
  DARK_FALZ_3,
  DARK_GUNNER,
  DARVANT,
  DARVANT_ULTIMATE,
  DE_ROL_LE,
  DE_ROL_LE_BODY,
  DE_ROL_LE_MINE,
  DEATH_GUNNER,
  DEL_LILY,
  DEL_RAPPY,
  DEL_RAPPY_ALT,
  DELBITER,
  DELDEPTH,
  DELSABER,
  DIMENIAN,
  DOLMDARL,
  DOLMOLM,
  DORPHON,
  DORPHON_ECLAIR,
  DRAGON,
  DUBCHIC,
  DUBWITCH, // Has no entry in battle params
  EGG_RAPPY,
  EPSIGUARD,
  EPSILON,
  EVIL_SHARK,
  GAEL,
  GAL_GRYPHON,
  GARANZ,
  GEE,
  GI_GUE,
  GIBBLES,
  GIGOBOOMA,
  GILLCHIC,
  GIRTABLULU,
  GOBOOMA,
  GOL_DRAGON,
  GORAN,
  GORAN_DETONATOR,
  GRASS_ASSASSIN,
  GUIL_SHARK,
  HALLO_RAPPY,
  HIDOOM,
  HILDEBEAR,
  HILDEBLUE,
  ILL_GILL,
  KONDRIEU,
  LA_DIMENIAN,
  LOVE_RAPPY,
  MERICAROL,
  MERICUS,
  MERIKLE,
  MERILLIA,
  MERILTAS,
  MERISSA_A,
  MERISSA_AA,
  MIGIUM,
  MONEST,
  MORFOS,
  MOTHMANT,
  NANO_DRAGON,
  NAR_LILY,
  OLGA_FLOW_1,
  OLGA_FLOW_2,
  PAL_SHARK,
  PAN_ARMS,
  PAZUZU,
  PAZUZU_ALT,
  PIG_RAY,
  POFUILLY_SLIME,
  POUILLY_SLIME,
  POISON_LILY,
  PYRO_GORAN,
  RAG_RAPPY,
  RECOBOX,
  RECON,
  SAINT_MILLION,
  SAINT_RAPPY,
  SAND_RAPPY,
  SAND_RAPPY_ALT,
  SATELLITE_LIZARD,
  SATELLITE_LIZARD_ALT,
  SAVAGE_WOLF,
  SHAMBERTIN,
  SINOW_BEAT,
  SINOW_BERILL,
  SINOW_GOLD,
  SINOW_SPIGELL,
  SINOW_ZELE,
  SINOW_ZOA,
  SO_DIMENIAN,
  UL_GIBBON,
  VOL_OPT_1,
  VOL_OPT_2,
  VOL_OPT_AMP,
  VOL_OPT_CORE,
  VOL_OPT_MONITOR,
  VOL_OPT_PILLAR,
  YOWIE,
  YOWIE_ALT,
  ZE_BOOTA,
  ZOL_GIBBON,
  ZU,
  ZU_ALT,
  MAX_ENEMY_TYPE,
};

template <>
const char* phosg::name_for_enum<EnemyType>(EnemyType type);
template <>
EnemyType phosg::enum_for_name<EnemyType>(const char* name);

bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type);
uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type);
uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type);
const std::vector<EnemyType>& enemy_types_for_rare_table_index(Episode episode, uint8_t rt_index);
bool enemy_type_is_rare(EnemyType type);
EnemyType rare_type_for_enemy_type(EnemyType base_type, Episode episode, uint8_t event, uint8_t floor);
