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

#define PIN_LCD_CS    12
#define PIN_LCD_SCLK  38
#define PIN_LCD_D0     4
#define PIN_LCD_D1     5
#define PIN_LCD_D2     6
#define PIN_LCD_D3     7
#define PIN_LCD_RST    2
#define PIN_I2C_SDA   15
#define PIN_I2C_SCL   14

#define DISP_W 480
#define DISP_H 480

#define C_BG      0x0841u
#define C_PANEL   0x1082u
#define C_CARD    0x18C3u
#define C_BORDER  0x39C7u
#define C_TEXT    0xFFFFu
#define C_MUTE    0xBDF7u
#define C_OK      0x3666u
#define C_WARN    0xECA0u
#define C_BUTTON  0x2145u
#define C_BUTTON2 0x3186u

#define FONT_BODY u8g2_font_9x15_t_cyrillic
#define FONT_SMALL u8g2_font_6x13_t_cyrillic

Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
    PIN_LCD_CS, PIN_LCD_SCLK, PIN_LCD_D0, PIN_LCD_D1, PIN_LCD_D2, PIN_LCD_D3);
Arduino_CO5300 *gfx = new Arduino_CO5300(
    gBus, PIN_LCD_RST, 0, DISP_W, DISP_H, 0, 0, 0, 0);

static void drawPanel(int x, int y, int w, int h, uint16_t fill, uint16_t border, int radius = 10) {
  gfx->fillRoundRect(x, y, w, h, radius, fill);
  gfx->drawRoundRect(x, y, w, h, radius, border);
}

static void drawDefaultText(int x, int y, const char *text, uint16_t color, uint8_t size = 1) {
  gfx->setFont();
  gfx->setTextSize(size);
  gfx->setTextColor(color);
  gfx->setCursor(x, y);
  gfx->print(text);
}

static void drawU8Text(int x, int y, const String &text, uint16_t color, const uint8_t *font) {
  gfx->setTextSize(1);
  gfx->setFont(font);
  gfx->setTextColor(color);
  gfx->setCursor(x, y);
  gfx->print(text);
}

static void drawButton(int x, int y, int w, int h, uint16_t fill, const String &label, const uint8_t *font, bool useDefaultFont = false) {
  drawPanel(x, y, w, h, fill, C_BORDER, 12);
  if (useDefaultFont) {
    drawDefaultText(x + 14, y + 30, label.c_str(), C_TEXT, 2);
    return;
  }
  drawU8Text(x + 14, y + 32, label, C_TEXT, font);
}

static void drawScreen() {
  gfx->fillScreen(C_BG);

  drawPanel(12, 12, 456, 456, C_PANEL, C_BORDER, 16);
  drawDefaultText(28, 42, "TEXT TEST 123", C_TEXT, 2);
  drawU8Text(28, 72, "Default ASCII above", C_MUTE, (const uint8_t *)FONT_SMALL);

  drawPanel(24, 90, 432, 72, C_CARD, C_BORDER, 12);
  drawDefaultText(38, 118, "A: Default font ABC123", C_TEXT, 2);
  drawDefaultText(38, 146, "Visible? then base path OK", C_WARN, 1);

  drawPanel(24, 174, 432, 84, C_CARD, C_BORDER, 12);
  drawU8Text(38, 204, "B: U8g2 ASCII abc123", C_TEXT, (const uint8_t *)FONT_BODY);
  drawU8Text(38, 230, "C: Русский текст 123", C_OK, (const uint8_t *)FONT_BODY);

  drawPanel(24, 270, 432, 84, C_CARD, C_BORDER, 12);
  drawU8Text(38, 298, "D: Мелкий шрифт кнопок", C_TEXT, (const uint8_t *)FONT_SMALL);
  drawU8Text(38, 320, "Если это видно, FONT_SMALL жив", C_MUTE, (const uint8_t *)FONT_SMALL);

  drawButton(24, 368, 128, 72, C_BUTTON, "BTN 1", nullptr, true);
  drawButton(176, 368, 128, 72, C_OK, "abc123", (const uint8_t *)FONT_BODY);
  drawButton(328, 368, 128, 72, C_BUTTON2, "Русский", (const uint8_t *)FONT_BODY);
}

void setup() {
  Serial.begin(115200);
  Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
  gfx->begin();
  gBus->writeC8D8(0x36, 0xA0);
  gfx->setBrightness(220);
  gfx->setUTF8Print(true);
  drawScreen();
}

void loop() {
  delay(1000);
}
