#include "cube_orientation.h"

namespace cube {

CubeCanvas::CubeCanvas(rgb_matrix::Canvas* base, int face_w, int face_h,
                       const int rot_deg_cw[6])
    : base_(base), fw_(face_w), fh_(face_h) {
  for (int i = 0; i < 6; i++) rot_[i] = rot_deg_cw[i];
}

void CubeCanvas::SetBase(rgb_matrix::Canvas* base) { base_ = base; }

int CubeCanvas::width() const { return base_->width(); }
int CubeCanvas::height() const { return base_->height(); }

void CubeCanvas::ApplyRotation(int face, int& x, int& y) const {
  int r = rot_[face] % 360;
  if (r < 0) r += 360;

  const int ox = x;
  const int oy = y;

  switch (r) {
    case 90:
      x = fh_ - 1 - oy;
      y = ox;
      break;
    case 180:
      x = fw_ - 1 - ox;
      y = fh_ - 1 - oy;
      break;
    case 270:
      x = oy;
      y = fw_ - 1 - ox;
      break;
    default:
      break;
  }
}

void CubeCanvas::SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
  if (x < 0 || y < 0) return;

  const int face = x / fw_;
  if (face < 0 || face > 5) {
    base_->SetPixel(x, y, r, g, b);
    return;
  }

  int lx = x - face * fw_;
  int ly = y;

  ApplyRotation(face, lx, ly);

  base_->SetPixel(face * fw_ + lx, ly, r, g, b);
}

void CubeCanvas::Clear() { base_->Clear(); }
void CubeCanvas::Fill(uint8_t r, uint8_t g, uint8_t b) { base_->Fill(r, g, b); }

}  // namespace cube
