// 20260213 ChatGPT
// $Id$
// $HeadURL$

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

#ifndef OLED_SDA
#define OLED_SDA 17
#endif

#ifndef OLED_SCL
#define OLED_SCL 18
#endif

#ifndef OLED_ADDR
#define OLED_ADDR 0x3C
#endif

// LilyGO T-Beam Supreme uses SH1106 OLED on I2C.
U8G2_SH1106_128X64_NONAME_F_HW_I2C oled(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

static const uint8_t kMaxLines = 5;
static String g_lines[kMaxLines];
static uint32_t g_iteration = 1;
static uint32_t g_pageCounter = 1;

static void addLine(const String& line) {
  for (uint8_t i = 0; i < kMaxLines - 1; ++i) {
    g_lines[i] = g_lines[i + 1];
  }
  g_lines[kMaxLines - 1] = line;
}

static void drawLines() {
  oled.clearBuffer();
  oled.setFont(u8g2_font_6x10_tf);

  const int yStart = 12;
  const int yStep = 12;
  for (uint8_t i = 0; i < kMaxLines; ++i) {
    if (g_lines[i].length() == 0) {
      continue;
    }
    oled.drawUTF8(0, yStart + (i * yStep), g_lines[i].c_str());
  }
  oled.sendBuffer();
}

static void clearLines() {
  for (uint8_t i = 0; i < kMaxLines; ++i) {
    g_lines[i] = "";
  }
}

static void showCentered(const char* line1, const char* line2 = nullptr, const char* line3 = nullptr) {
  oled.clearBuffer();
  oled.setFont(u8g2_font_6x10_tf);

  if (line1) oled.drawUTF8(0, 16, line1);
  if (line2) oled.drawUTF8(0, 32, line2);
  if (line3) oled.drawUTF8(0, 48, line3);

  oled.sendBuffer();
}

static void demo1_scrollingHello() {
  Serial.println("Demo 1/3: scrolling Hello #");
  clearLines();
  for (uint8_t i = 0; i < 10; ++i) {
    String line = "Hello #" + String(g_iteration++);
    addLine(line);
    drawLines();
    delay(1000);
  }
}

static void demo2_clearAfterTen() {
  Serial.println("Demo 2/3: clear screen after 10");
  clearLines();
  for (uint8_t i = 1; i <= 10; ++i) {
    String line = "Count " + String(i);
    addLine(line);
    drawLines();
    delay(500);
  }

  showCentered("Demo 2", "Clearing screen...");
  delay(1000);
  oled.clearDisplay();
  oled.sendBuffer();
  delay(1000);
}

static void drawPage(uint8_t page) {
  oled.clearBuffer();
  oled.setFont(u8g2_font_6x10_tf);

  if (page == 0) {
    oled.drawUTF8(0, 12, "Demo 3 - Page 1/3");
    oled.drawUTF8(0, 28, "GPS: 37.7749 N");
    oled.drawUTF8(0, 40, "LON: 122.4194 W");
    oled.drawUTF8(0, 56, "Fix: 3D");
  } else if (page == 1) {
    oled.drawUTF8(0, 12, "Demo 3 - Page 2/3");
    oled.drawUTF8(0, 28, "LoRa RSSI: -92 dBm");
    oled.drawUTF8(0, 40, "LoRa SNR:  +8.5 dB");
    oled.drawUTF8(0, 56, "Pkts: " );
    oled.setCursor(38, 56);
    oled.print(g_pageCounter++);
  } else {
    oled.drawUTF8(0, 12, "Demo 3 - Page 3/3");
    oled.drawUTF8(0, 28, "Node: TBM-SUPREME");
    oled.drawUTF8(0, 40, "Mode: Field Test");
    oled.drawUTF8(0, 56, "OLED refresh demo");
  }

  oled.sendBuffer();
}

static void demo3_threePages() {
  Serial.println("Demo 3/3: three-page rotation");
  for (uint8_t round = 0; round < 3; ++round) {
    drawPage(0);
    delay(700);
    drawPage(1);
    delay(700);
    drawPage(2);
    delay(700);
  }
}

static void showRestartBanner() {
  Serial.println("Restarting 3 demos");
  showCentered("Restarting 3 demos", "Cycle begins again", "in 5 seconds...");
  delay(5000);
}

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

  Wire.begin(OLED_SDA, OLED_SCL);
  oled.setI2CAddress(OLED_ADDR << 1); // U8g2 expects 8-bit address.
  oled.begin();

  oled.clearBuffer();
  oled.setFont(u8g2_font_6x10_tf);
  oled.drawUTF8(0, 12, "Exercise 02 OLED");
  oled.sendBuffer();

  Serial.println("Exercise 02: OLED display loop");
  Serial.printf("OLED SDA=%d SCL=%d ADDR=0x%02X\r\n", OLED_SDA, OLED_SCL, OLED_ADDR);
}

void loop() {
  demo1_scrollingHello();
  demo2_clearAfterTen();
  demo3_threePages();
  showRestartBanner();
}
