#pragma once
#include "../../ship.hpp"
#include "fighter-info.hpp"
//! самый первый чёрный истребитель в игре
class Fighter: public Enemy {
public:
  Counter missile_delay = {}; ///< задерка ракеты
  Counter vulkan_delay = {}; ///< задерка пуль мулемёта
  Vec target = {}; ///< цель, на которую летит истребитель
  Fighter() = default;
  ~Fighter() = default;
  Fighter& operator = (CN(Fighter)) = default;
  void clear() override { *this = {}; }
  constx uint static_id = ENE_FIGHTER;
  constexpr uint get_id() const override { return static_id; };
  void init() override {
    Enemy::init();
    smoke = smoke_bank::big;
    expl = expl_bank::dir_big;
    flags |= EF_NO_SCATTER;
    auto info = rcast(CP(Fighter_info), p_info);
    hp = info->hp;
    phys.rst = info->resist;
    set_target(); // переназначить цель после смерти
    missile_delay.set_count(info->missile_delay);
    vulkan_delay.set_count(info->vulkan_delay);
  }
  bool draw(Image& dst, CN(Vec) offset) const override {
    if ( !Enemy::draw(dst, offset))
      return false;
    return true;
  }
  bool update(float dt, uint update_idx) override {
    if ( !Enemy::update(dt, update_idx))
      return false;
    auto info = rcast(CP(Fighter_info), p_info);
    phys.rotate_to(target, info->rot_accel, dt); // поворачивать в target
    if (diffclt2num(Game::difficulty) > uint(Difficulty::NORMAL)) {
      // направляясь к игроку истребитель ускоряется
      phys.add_spd(std::abs(phys.degvec(target)) <= 45.0f
        ? info->accel
        : -info->reverse, dt);
    } else {
      // при приследывании истребитель ускоряется
      phys.add_spd(g_offset.leaving(phys)
        ? info->accel
        : -info->reverse, dt);
    }
    // по достижении целевых кординат выбираются другие
    if (distance(target, phys.pos) <= 12.0f)
      set_target();
    if (p_plr->is_live())
      attack(info, dt);
    phys.spd = std::clamp(phys.spd, info->min_spd, info->max_spd);
    return true;
  }
  static void load(CN(a83::Str) dir_name);
  void kill() override {
    Enemy::kill();
    make_shards();
  }
protected:
  void make_shards(); ///< вылет случайных осколков
  //! назначить новые корды для движения
  void set_target() {
    // огонь с упреждением
    if (Game::difficulty == Difficulty::DIE
    || Game::difficulty == Difficulty::HARD) {
      auto info = rcast(CP(Fighter_info), p_info);
      target = Phys::predict(phys.pos, phys.spd + info->bullet_speed, g_offset);
    } else { // цель возле игрока
      target = deg2vec(rand_deg());
      target *= 42.0f; // чтоб не стоять в игроке
    }
  } // set_target
  void attack(CP(Fighter_info) info, float dt) {
    // ракеты
    if (missile_delay()) {
      missile_delay.reset_all();
      if (auto p = add_blt(BLT_MISSILE_3); p) {
        p->phys = Phys(phys.pos, phys.deg, 0,
          phys.spd + info->missile_speed);
        p->flags |= EF_WARN_BLT | EF_IGNORE_MASTER;
        p->master = this;
        p->smoke = smoke_bank::small;
        p->expl = expl_bank::dir_small;
        p->light = Light(0.4f, 0, 15, LF_RSIZE | LF_INFINITY
          | LF_RAND | LF_STAR, {0, 3});
        p->pf0 = &Enity::homing_plr;
        p->data0.f0 = info->missile_accel_rot;
      }
    }
    missile_delay.update(dt);
    // выстрел из пулемёта
    if (vulkan_delay()
    // стрелять с опр-го раст-я
    && (distance({}, phys.pos) <= info->shoot_dist) ) {
      vulkan_delay.reset_all();
      if (auto p = add_blt(BLT_VULKAN); p) {
        p->phys = Phys(phys.pos, phys.deg, 0, phys.spd
          + info->bullet_speed - a83::frand() * 600.0f); // рандом скорость пуль
        p->flags |= EF_R_FRAME_ANY | EF_IGNORE_MASTER;
        p->master = this;
        p->expl = expl_bank::bullet_crush;
        p->blend_mode = BM::diff;
        p->light = Light(1.5f, 0, 7.5f,
          LF_RSIZE | LF_NOSTAR | LF_RAND | LF_INFINITY, {1, -10});
      }
    }
    vulkan_delay.update(dt);
  } // attack
}; // Fighter
#include "fighter-load.cpp"
#include "fighter-shards.cpp"