#include "sprite.hpp"
void Sprite::cut(int sx, int sy, int mx, int my, Sprite& dst) const {
  if (mx < 1 || my < 1)
    return;
  dst.init(mx, my, offset);
  cauto ex = sx + mx;
  cauto ey = sy + my;
  if (tex.check()) {
    for (auto y = sy; y < ey; ++y)
    for (auto x = sx; x < ex; ++x)
      dst.tex.fast_set(x - sx, y - sy, tex.fast_get(x, y));
  }
  if (mask.check()) {
    for (auto y = sy; y < ey; ++y)
    for (auto x = sx; x < ex; ++x)
      dst.mask.fast_set(x - sx, y - sy, mask.fast_get(x, y));
  }
}
void Sprite::optimize_size() {
  if ( !check())
    return;
  int sx = mask.getX() - 1;
  int ex = -1;
  int sy = mask.getY() - 1;
  int ey = -1;
// по наличию непрозрачного пикселя в маске определяется область для вырезания
  for (int y = 0; y < mask.getY(); ++y)
  for (int x = 0; x < mask.getX(); ++x)
    if (mask.fast_get(x,y) != Color::WHITE) {
      if (x < sx)
        sx = x;
      if (x > ex)
        ex = x;
      if (y < sy)
        sy = y;
      if (y > ey)
        ey = y;
    }
  Image(tex) .fast_cut(sx, sy, ex - sx + 1, ey - sy + 1, tex );
  Image(mask).fast_cut(sx, sy, ex - sx + 1, ey - sy + 1, mask);
  offset += Vec(sx, sy);
}
void Sprite::make_rotated(float deg, Sprite& dst) const {
  using namespace a83;
  if ( !check())
    return;
// 1. выбирается самая длинная сторона src
  int longest = std::max(tex.getX(), tex.getY());
// 2. создаётся квадрат с размером длинной стороны * 2.8
  constexpr float scaler = 1.4f;
  int image_size = longest * scaler * 2.0f;
  int past_pos = longest * scaler;
// 3. к офсэту на выходе прибавляется src.X * 1.4 
  cauto rad = deg2rad(deg);
  dst.offset = offset.get_rotate_rad({0, 0}, rad) - Vec(past_pos, past_pos);
// 4. крути & оптимизация по размеру
  dst.tex.init(image_size, image_size, Color::RED);
  tex.print_rotated(dst.tex, past_pos, past_pos, 0, 0, deg);
  dst.mask.init(image_size, image_size, Color::WHITE);
  mask.print_rotated(dst.mask, past_pos, past_pos, 0, 0, deg);
  dst.optimize_size();
  vp_delete(dst.hits);
}
//! draw with no offset correction (4 tiles)
void Sprite::print_mask_noffset(int x, int y, Image& dst) const
  { tex.print_mask(x, y, dst, mask); }
void Sprite::print_mask(CN(Vec) pos, Image& dst) const {
  mask_light.print_add_safe(pos.x + offset.x - 1, pos.y + offset.y - 1, dst);
  tex.print_mask(pos.x + offset.x, pos.y + offset.y, dst, mask);
}
void Sprite::print_blink2(Image& dst, CN(Vec) pos, int timer) const
  { if (timer & 1) print_mask(pos, dst); }
//! рисует изображение мигающее каждую строку
void Sprite::print_blink_line2(Image& dst, CN(Vec) pos, int timer) const {
  for (int y = 0; y < mask.getY(); ++y)
  for (int x = 0; x < mask.getX(); ++x)
    if ((y & 1) ^ (timer & 1) && !mask.get(x, y).val) {
      cauto pos_x = pos.x + x + offset.x;
      cauto pos_y = pos.y + y + offset.y;
      dst.set(pos_x, pos_y, tex.get(x, y));
    }
}
void Sprite::print(CN(Vec) pos, Sprite& dst) const {
  if ( !check() or !dst.check())
    return;
  cauto posx_ = pos.x + offset.x;
  cauto posy_ = pos.y + offset.y;
  this->tex.print(posx_, posy_, dst.tex);
  this->mask.print(posx_, posy_, dst.mask);
  this->mask_light.print(posx_, posy_, dst.mask_light);
}
void Sprite::make_light_mask(CN(Image) mask_, CN(Color) alpha, LightMode mode) {
  if ( !mask_.check() or mode == LightMode::none) 
    return;
  mask_light.init(mask_.getX() + 2, mask_.getY() + 2, alpha);
  mask_.print(1, 1, mask_light);
  mask_light.pixel_expand(alpha, (mode == LightMode::way8));
  mask_light.invert();
  // добавка подсветки
  mask_light.add( -(Color::GRAY_COUNT
    - Color::GRAY_COUNT * mask_light_ratio) );
}