#include <Arduino.h>
#include <Arduino_GFX_Library.h>

// JC4827W543C 螢幕解析度
constexpr int SCREEN_WIDTH = 480;
constexpr int SCREEN_HEIGHT = 272;

// 背光控制腳位
constexpr int TFT_BACKLIGHT = 1;

/*
 * JC4827W543C QSPI 接線
 *
 * CS  = GPIO45
 * SCK = GPIO47
 * D0  = GPIO21
 * D1  = GPIO48
 * D2  = GPIO40
 * D3  = GPIO39
 */
Arduino_DataBus *bus = new Arduino_ESP32QSPI(
    45, // CS
    47, // SCK
    21, // D0
    48, // D1
    40, // D2
    39  // D3
);

/*
 * NV3041A 螢幕控制器
 *
 * GFX_NOT_DEFINED：沒有獨立的螢幕 RESET 腳位
 * 0：畫面旋轉方向
 * true：IPS 螢幕
 */
Arduino_GFX *panel = new Arduino_NV3041A(
    bus,
    GFX_NOT_DEFINED,
    0,
    true
);

// 建立 480 × 272 畫布
Arduino_GFX *gfx = new Arduino_Canvas(
    SCREEN_WIDTH,
    SCREEN_HEIGHT,
    panel
);

void setup()
{
  Serial.begin(115200);

  // 最多等待 USB CDC Serial 10 秒
  unsigned long serialStart = millis();

  while (!Serial && millis() - serialStart < 10000)
  {
    delay(10);
  }

  Serial.println();
  Serial.println("JC4827W543C display test starting...");

  // 開啟背光
  pinMode(TFT_BACKLIGHT, OUTPUT);
  digitalWrite(TFT_BACKLIGHT, HIGH);

  // 初始化螢幕
  if (!gfx->begin())
  {
    Serial.println("Display initialization failed");

    while (true)
    {
      delay(1000);
    }
  }

  Serial.println("Display initialized");

  // 清除畫面
  gfx->fillScreen(RGB565_BLACK);

  // 上方藍色標題列
  gfx->fillRect(
      0,
      0,
      SCREEN_WIDTH,
      70,
      RGB565_BLUE
  );

  // 標題
  gfx->setTextColor(RGB565_WHITE);
  gfx->setTextSize(3);
  gfx->setCursor(45, 22);
  gfx->println("JC4827W543C");

  // 中間文字
  gfx->setTextColor(RGB565_GREEN);
  gfx->setTextSize(3);
  gfx->setCursor(75, 115);
  gfx->println("Hello Kubuntu!");

  // 底部文字
  gfx->setTextColor(RGB565_YELLOW);
  gfx->setTextSize(2);
  gfx->setCursor(105, 180);
  gfx->println("ESP32-S3 + Arduino");

  // 畫出彩色測試方塊
  gfx->fillRect(105, 220, 50, 30, RGB565_RED);
  gfx->fillRect(165, 220, 50, 30, RGB565_GREEN);
  gfx->fillRect(225, 220, 50, 30, RGB565_BLUE);
  gfx->fillRect(285, 220, 50, 30, RGB565_WHITE);

  // Arduino_Canvas 必須呼叫 flush() 才會顯示
  gfx->flush();

  Serial.println("Test screen rendered");
}

void loop()
{
  static unsigned long previousMillis = 0;

  if (millis() - previousMillis >= 1000)
  {
    previousMillis = millis();

    Serial.printf(
        "Running: %lu ms\n",
        millis()
    );
  }
}
