#pragma once
#include "image.hpp"
#include "common/Vec.hpp"
#include "common/figure.hpp"
#include "common/archive.hpp"
namespace {
  static float mask_light_ratio = 1.0f; ///< усилитель маски свечения
}
//! спрайт содержит картинку и маску прозрачности для неё
class Sprite {
public:
  //! типы подсветки спрайта
  enum class LightMode {
    none = 0, ///< не использовать
    way4, ///< растекание пикселей в 4-х направлениях
    way8, ///< растекание пикселей в 8-х направлениях
  };
  Image tex = {};
  Image mask = {}; //!< WHITE в маске значит прозрачность в 100%
  Image mask_light = {}; //!< маска подсветки
  Vec offset = {};
  vp_figure_t hits = {};
  Sprite() = default;
  Sprite(int mx, int my, CN(Vec) _offset = {}, CN(vp_figure_t) _hits = {},
  LightMode mode = {})
    { init(mx, my, _offset, _hits, mode); }
  Sprite(CN(Sprite) in) { init_copy(in); }
  Sprite& operator = (CN(Sprite) in) {
    init_copy(in);
    return *this;
  }
  ~Sprite() { free(); }
  bool check() const { return tex.check() and mask.check(); }
  void init(int mx, int my, CN(Vec) _offset = {},
  CN(vp_figure_t) _hits = {}, LightMode mode = {}) {
    free();
    tex.init(mx, my);
    mask.init(mx, my);
    if (mode != LightMode::none)
      mask_light.init(mx + 2, my + 2);
    offset = _offset;
    for (cnauto it: _hits)
      hits.push_back(make_figure(*it));
  }
  void init_copy(CN(Sprite) in) {
    init(in.tex.getX(), in.tex.getY(), in.offset, in.hits);
    in.tex.fast_print(tex);
    in.mask.fast_print(mask);
  }
  void free() { 
    tex.free();
    mask.free();
    mask_light.free();
    vp_delete(hits);
  }
// sprite.cpp:
  void cut(int sx, int sy, int mx, int my, Sprite& dst) const; //!< вырезать часть спрайта. записать в dst
  //! поворачивает спрайты с оптимизацией по размеру
  void make_rotated(float deg, Sprite& dst) const;
  void optimize_size(); //!< оптимизация полезного пространства в спрайте
  //! draw with no offset correction (4 tiles)
  void print_mask_noffset(int x, int y, Image& dst) const;
  void print_mask(CN(Vec) pos, Image& dst) const;
  //! рисует спрайт на другой с наложением в маску
  void print(CN(Vec) pos, Sprite& dst) const;
  //! вывод с миганием каждйы второй кадр
  void print_blink2(Image& dst, CN(Vec) pos, int timer) const;
  void fast_print(Image& dst, bool use_mask_light = false) const
    { tex.fast_print_mask(dst, mask, mask_light, use_mask_light); }
  //! рисует изображение мигающее шахматной сеткой
  template<blend_pf f>
  void make_print_blink_dot2(Image& dst, CN(Vec) pos, int timer) const;
  template<blend_pf pf> void make_print_mask(CN(Vec) pos, Image& dst) const;
  void print_blink_dot2(Image& dst, CN(Vec) pos, int timer) const;
  void print_blink_dot2_diff(Image& dst, CN(Vec) pos, int timer) const;
  //! рисует изображение мигающее каждую строку
  void print_blink_line2(Image& dst, CN(Vec) pos, int timer) const;
  // мигание спрайта используемое в игре
  #define print_blink print_blink_dot2
  //! создание маски освящения
  void make_light_mask(CN(Image) mask_, CN(Color) alpha, LightMode mode);
// sprite-io.cpp:
  //! загрузка спрайта
  void load(a83::Str name, CN(Vec) _offset = {}, LightMode mode = {});
  Sprite(CN(a83::Str) name, CN(Vec) _offset = {}, LightMode mode = {})
    { load(name, _offset, mode); }
  void init(CN(a83::Str) name, CN(Vec) _offset = {}, LightMode mode = {})
    { load(name, _offset, mode); }
  //! загрузка спрайта из памяти архива
  void load(CN(Archive) arch, CN(a83::Str) fname, CN(Vec) _offset = {},
    LightMode mode = {});
  Sprite(CN(Archive) arch, CN(a83::Str) fname, CN(Vec) _offset = {},
  LightMode mode = {})
    { load(arch, fname, _offset, mode); }
  void init(CN(Archive) arch, CN(a83::Str) fname, CN(Vec) _offset = {},
  LightMode mode = {})
    { load(arch, fname, _offset, mode); }
  //! декодировать данные картинки из памяти
  void decode(CN(data_t) mem, CN(Vec) _offset = {}, LightMode mode = {});
};
#include "sprite-tmpl.hpp"
#include "sprite-io.cpp"
#include "sprite.cpp"