#pragma once

#include "Runtime/RetroTypes.hpp"
#include "Runtime/Weapon/CWeaponMode.hpp"

namespace metaforce {

enum class EVulnerability { Weak, Normal, Deflect, Immune, PassThrough, DirectWeak, DirectNormal, DirectImmune };
enum class EDeflectType { None, One, Two, Three, Four };

class CDamageVulnerability {
  std::array<EVulnerability, 15> x0_normal;
  std::array<EVulnerability, 4> x3c_charged;
  std::array<EVulnerability, 4> x4c_combo;
  EDeflectType x5c_deflected;
  EDeflectType x60_chargedDeflected{};
  EDeflectType x64_comboDeflected{};

  void ConstructNew(CInputStream& in, int propCount);

  static const CDamageVulnerability sNormalVulnerability;
  static const CDamageVulnerability sImmuneVulnerability;
  static const CDamageVulnerability sReflectVulnerability;
  static const CDamageVulnerability sPassThroughVulnerability;

public:
  explicit CDamageVulnerability(CInputStream& in);

  constexpr CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma,
                                 EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile,
                                 EVulnerability boostBall, EVulnerability phazon, EVulnerability enemyWp1,
                                 EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4,
                                 EVulnerability v1, EVulnerability v2, EDeflectType deflectType)
  : x0_normal({power, ice, wave, plasma, powerBomb, missile, boostBall, phazon, enemyWp1, enemyWp2, enemyWp3, enemyWp4,
               v1, v2})
  , x3c_charged({x0_normal[0], x0_normal[1], x0_normal[2], x0_normal[3]})
  , x4c_combo({x0_normal[0], x0_normal[1], x0_normal[2], x0_normal[3]})
  , x5c_deflected(deflectType) {}

  constexpr CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma,
                                 EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile,
                                 EVulnerability boostBall, EVulnerability phazon, EVulnerability enemyWp1,
                                 EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4,
                                 EVulnerability v1, EVulnerability v2, EVulnerability chargedPower,
                                 EVulnerability chargedIce, EVulnerability chargedWave, EVulnerability chargedPlasma,
                                 EVulnerability superMissile, EVulnerability iceSpreader, EVulnerability waveBuster,
                                 EVulnerability flameThrower, EDeflectType deflected)
  : x0_normal({power, ice, wave, plasma, powerBomb, missile, boostBall, phazon, enemyWp1, enemyWp2, enemyWp3, enemyWp4,
               v1, v2})
  , x3c_charged({chargedPower, chargedIce, chargedWave, chargedPlasma})
  , x4c_combo({superMissile, iceSpreader, waveBuster, flameThrower})
  , x5c_deflected(deflected) {}

  EDeflectType GetDeflectionType(const CWeaponMode& mode) const;

  bool WeaponHurts(const CWeaponMode&, bool ignoreDirect) const;
  bool WeaponHits(const CWeaponMode& mode, bool checkDirect) const;
  EVulnerability GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const;

  static const CDamageVulnerability& NormalVulnerabilty() { return sNormalVulnerability; }
  static const CDamageVulnerability& ImmuneVulnerabilty() { return sImmuneVulnerability; }
  static const CDamageVulnerability& ReflectVulnerabilty() { return sReflectVulnerability; }
  static const CDamageVulnerability& PassThroughVulnerabilty() { return sPassThroughVulnerability; }
};
} // namespace metaforce
