// face_id.cc - paint each face with a color + big face number (0-5)
// Build:
//   g++ -std=c++17 -O2 -Wall -Wextra -I../rpi-rgb-led-matrix/include \
//     face_id.cc -L../rpi-rgb-led-matrix/lib -lrgbmatrix -lrt -lm -lpthread -o face_id
//
// Run example:
//   sudo ./face_id --led-rows=64 --led-cols=64 --led-chain=6 \
//     --led-gpio-mapping=adafruit-hat --led-slowdown-gpio=6

#include <csignal>
#include <cstdint>
#include <cstring>
#include <chrono>
#include <thread>
#include <algorithm>
#include <iostream>

#include "led-matrix.h"

using rgb_matrix::RGBMatrix;
using rgb_matrix::FrameCanvas;

static volatile sig_atomic_t g_running = 1;
static void SigHandler(int) { g_running = 0; }

// Simple 5x7 digit font (only '0'..'5' used here)
static const uint8_t kDigit5x7[10][7] = {
  // each row is 5 bits, MSB on left (bit 4)
  {0b01110,0b10001,0b10011,0b10101,0b11001,0b10001,0b01110}, //0
  {0b00100,0b01100,0b00100,0b00100,0b00100,0b00100,0b01110}, //1
  {0b01110,0b10001,0b00001,0b00010,0b00100,0b01000,0b11111}, //2
  {0b11110,0b00001,0b00001,0b01110,0b00001,0b00001,0b11110}, //3
  {0b00010,0b00110,0b01010,0b10010,0b11111,0b00010,0b00010}, //4
  {0b11111,0b10000,0b10000,0b11110,0b00001,0b00001,0b11110}, //5
  {0b00110,0b01000,0b10000,0b11110,0b10001,0b10001,0b01110}, //6
  {0b11111,0b00001,0b00010,0b00100,0b01000,0b01000,0b01000}, //7
  {0b01110,0b10001,0b10001,0b01110,0b10001,0b10001,0b01110}, //8
  {0b01110,0b10001,0b10001,0b01111,0b00001,0b00010,0b01100}  //9
};

static void DrawDigit(FrameCanvas* c, int x0, int y0, int scale, int digit,
                      uint8_t r, uint8_t g, uint8_t b) {
  digit = std::clamp(digit, 0, 9);
  for (int row = 0; row < 7; ++row) {
    uint8_t bits = kDigit5x7[digit][row];
    for (int col = 0; col < 5; ++col) {
      bool on = (bits >> (4 - col)) & 1;
      if (!on) continue;
      int px = x0 + col * scale;
      int py = y0 + row * scale;
      for (int dy = 0; dy < scale; ++dy)
        for (int dx = 0; dx < scale; ++dx)
          c->SetPixel(px + dx, py + dy, r, g, b);
    }
  }
}

int main(int argc, char** argv) {
  std::signal(SIGINT, SigHandler);
  std::signal(SIGTERM, SigHandler);

  RGBMatrix::Options options;
  rgb_matrix::RuntimeOptions rt;
  if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv, &options, &rt)) return 1;

  RGBMatrix* matrix = RGBMatrix::CreateFromOptions(options, rt);
  if (!matrix) {
    std::cerr << "Failed to create matrix\n";
    return 1;
  }

  matrix->SetBrightness(options.brightness ? options.brightness : 60);
  FrameCanvas* canvas = matrix->CreateFrameCanvas();

  // Face base colors (distinct but not blinding)
  const uint8_t face_rgb[6][3] = {
    {10, 10, 60},   // 0 TOP
    {60, 10, 10},   // 1 LEFT
    {10, 60, 10},   // 2 FRONT
    {60, 60, 10},   // 3 RIGHT
    {10, 60, 60},   // 4 BACK
    {60, 10, 60}    // 5 BOTTOM
  };

  while (g_running) {
    canvas->Clear();

    for (int face = 0; face < 6; ++face) {
      int ox = face * 64;
      int oy = 0;

      // Fill face background
      for (int y = 0; y < 64; ++y) {
        for (int x = 0; x < 64; ++x) {
          canvas->SetPixel(ox + x, oy + y,
                           face_rgb[face][0], face_rgb[face][1], face_rgb[face][2]);
        }
      }

      // Draw a big digit in the center
      int scale = 6;                 // 5*6=30 wide, 7*6=42 tall
      int digit_w = 5 * scale;
      int digit_h = 7 * scale;
      int x0 = ox + (64 - digit_w) / 2;
      int y0 = oy + (64 - digit_h) / 2;

      // Digit color: white-ish
      DrawDigit(canvas, x0, y0, scale, face, 200, 200, 200);
    }

    canvas = matrix->SwapOnVSync(canvas);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
  }

  canvas->Clear();
  canvas = matrix->SwapOnVSync(canvas);
  delete matrix;
  return 0;
}
