#include "Runtime/Particle/CUVElement.hpp"

/* Documentation at: https://wiki.axiodl.com/w/Particle_Script#UV_Elements */

namespace metaforce {

CUVEAnimTexture::CUVEAnimTexture(TToken<CTexture>&& tex, std::unique_ptr<CIntElement>&& tileW,
                                 std::unique_ptr<CIntElement>&& tileH, std::unique_ptr<CIntElement>&& strideW,
                                 std::unique_ptr<CIntElement>&& strideH, std::unique_ptr<CIntElement>&& cycleFrames,
                                 bool loop)
: x4_tex(std::move(tex)), x24_loop(loop), x28_cycleFrames(std::move(cycleFrames)) {
  tileW->GetValue(0, x10_tileW);
  tileH->GetValue(0, x14_tileH);
  strideW->GetValue(0, x18_strideW);
  strideH->GetValue(0, x1c_strideH);

  const int width = int(x4_tex.GetObj()->GetWidth());
  const int height = int(x4_tex.GetObj()->GetHeight());
  const float widthF = float(width);
  const float heightF = float(height);
  const int xTiles = std::max(1, width / x18_strideW);
  const int yTiles = std::max(1, height / x1c_strideH);

  x20_tiles = xTiles * yTiles;
  x2c_uvElems.reserve(x20_tiles);

  for (int y = yTiles - 1; y >= 0; --y) {
    for (int x = 0; x < xTiles; ++x) {
      const int px = x18_strideW * x;
      const int px2 = px + x10_tileW;
      const int py = x1c_strideH * y;
      const int py2 = py + x14_tileH;

      x2c_uvElems.push_back({
          float(px) / widthF,
          float(py) / heightF,
          float(px2) / widthF,
          float(py2) / heightF,
      });
    }
  }
}

void CUVEAnimTexture::GetValueUV(int frame, SUVElementSet& valOut) const {
  int cv = 1;
  x28_cycleFrames->GetValue(frame, cv);
  float cvf = float(cv) / float(x20_tiles);
  cvf = float(frame) / cvf;

  int tile = int(cvf);
  if (x24_loop) {
    // HACK
    // Check bad values for cvf
    tile = !(std::isnan(cvf) || std::isinf(cvf)) && int(cvf) >= 0 ? int(cvf) : 0;
    if (tile >= x20_tiles) {
      tile = tile % x20_tiles;
    }
  } else {
    if (cvf >= float(x20_tiles)) {
      tile = x20_tiles - 1;
    }
  }

  valOut = x2c_uvElems[tile];
}

} // namespace metaforce
