#include "image.hpp"
#include "a83/random.hpp"
#include "common/Vec.hpp"
template<int size> void Image::fast_blur() {
  static_assert(size > 1);
  uint buf_x, buf_y;
  for (int y = 0; y < Y - size; ++y)
  for (int x = 0; x < X - size; ++x) {
    buf_y = 0;
    for (int by = y; by < y + size; ++by) {
      buf_x = 0;
      for (int bx = x; bx < x + size; ++bx)
        buf_x += fast_get(bx, by).val;
      buf_y += buf_x / size;
    } // for by
    fast_set(x, y, buf_y / size);
  } // for y, x
}
void Image::rotate_90(Image &dst) const {
  if ( !check())
    return;
  dst.init(getY(), getX());
  for (int y = 0; y < dst.getY(); ++y)
  for (int x = 0; x < dst.getX(); ++x)
    dst.fast_set(x, y, fast_get(y, dst.getX() - x - 1));
}
void Image::rotate_180(Image &dst) const {
  if ( !check())
    return;
  dst.init(getY(), getX());
  for (int y = 0; y < dst.getY(); ++y)
  for (int x = 0; x < dst.getX(); ++x)
    dst.fast_set(x, y, fast_get(dst.getX() - x - 1, dst.getY() - y - 1));
}
void Image::rotate_270(Image &dst) const {
  if ( !check())
    return;
  dst.init(getY(), getX());
  for (int y = 0; y < dst.getY(); ++y)
  for (int x = 0; x < dst.getX(); ++x)
    dst.fast_set(x,y, fast_get(dst.getY() - y - 1, x));
}
void Image::mirror_v(Image &dst) const {
  if ( !check())
    return;
  dst.init(getY(), getX());
  for (int y = 0; y < dst.getY(); ++y)
  for (int x = 0; x < dst.getX(); ++x)
    dst.fast_set(x,y, fast_get(dst.getX() - x - 1, y));
}
void Image::mirror_h(Image& dst) const {
  if ( !check())
    return;
  dst.init(getY(), getX());
  for (int y = 0; y < dst.getY(); ++y)
  for (int x = 0; x < dst.getX(); ++x)
    dst.fast_set(x, y, fast_get(x, dst.getY() - y - 1));
}
void Image::mirror_hv(Image &dst) const {
  if ( !check())
    return;
  dst.init(getY(), getX());
  for (int y = 0; y < dst.getY(); ++y)
  for (int x = 0; x < dst.getX(); ++x)
    dst.fast_set(x,y, fast_get(dst.getX() - x - 1, dst.getY() - y - 1));
}
void Image::contrast2() {
  if ( !check())
    return;
  for (int i = 0; i < size(); ++i) {
    auto* prt = fast_get_ptr(i);
    prt->add(Color::WHITE2 / -2.0);
    prt->mul(2.0);
  }
} // contrast2
void Image::haze(CN(Vec) pos, int sz, int len, int cnt, float r) {
  #ifdef DEBUG
  if ( !check())
    return;
  #endif
  // выход, если это не на экране
  if (pos.x + r < 0 or
    pos.x - r > X or
    pos.y + r < 0 or
    pos.y - r > Y)
    return;
  if (sz < 1 or len < 1 or cnt < 1 or r <= 0)
    return;
  static Image tile;
  FOR (i, cnt) {
    // получить случайную точку копирования вокруг pos
    const Vec cut_pos(Vec::make_rand_by_radius(pos - (sz / 2), r));
    this->cut2img(cut_pos.x, cut_pos.y, sz, sz, tile);
    tile.print(
      cut_pos.x + a83::irand(-len, len),
      cut_pos.y + a83::irand(-len, len), *this);
  } // for cnt
} // haze