#include <Arduino.h>
#include <Wire.h>
#define LV_CONF_INCLUDE_SIMPLE
#include "lv_conf.h"
#include <lvgl.h>
#include <Arduino_GFX_Library.h>
#define TFT_SCLK   12
#define TFT_MOSI   11
#define TFT_MISO   13
#define TFT_CS     10
#define TFT_DC      9
#define TFT_RST    -1
#define TFT_BL     -1
#define I2C_SDA    17
#define I2C_SCL    18
#define BTN_UP     21
#define BTN_DOWN   16
#define BTN_OK     15
#define BTN_BACK   7
#define BUZZER_PIN 3
static const int BUZZER_CHANNEL = 0;
#define TFT_HOR_RES 320
#define TFT_VER_RES 240
#define LVGL_BUFFER_ROWS 40
#define TFT_ROTATION 1
Arduino_DataBus *bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCLK, TFT_MOSI, TFT_MISO);
Arduino_GFX *gfx = new Arduino_ILI9341(bus, TFT_RST, TFT_ROTATION);
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *buf1 = nullptr;
struct Button { uint8_t pin; bool lastState; uint32_t lastChange; };
Button buttons[] = { {BTN_UP,true,0},{BTN_DOWN,true,0},{BTN_OK,true,0},{BTN_BACK,true,0} };
static void lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
static void lvgl_tick_task(void *);
static void create_hello_ui();
static void beep(uint16_t freq, uint16_t ms);
static void scan_i2c();
void setup() {
  Serial.begin(115200);
  Wire.begin(I2C_SDA, I2C_SCL);
  delay(50);
  scan_i2c();
  for (auto &b : buttons) { pinMode(b.pin, INPUT_PULLUP); b.lastState = digitalRead(b.pin); b.lastChange = millis(); }
  if (BUZZER_PIN >= 0) { ledcAttachPin(BUZZER_PIN, BUZZER_CHANNEL); ledcWriteTone(BUZZER_CHANNEL, 0); }
  if (!gfx->begin()) { Serial.println("Display begin() failed"); while(true) delay(1000); }
  gfx->fillScreen(BLACK);
  lv_init();
  buf1 = (lv_color_t*)malloc(sizeof(lv_color_t) * TFT_HOR_RES * LVGL_BUFFER_ROWS);
  lv_disp_draw_buf_init(&draw_buf, buf1, NULL, TFT_HOR_RES * LVGL_BUFFER_ROWS);
  static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = TFT_HOR_RES; disp_drv.ver_res = TFT_VER_RES;
  disp_drv.flush_cb = lvgl_flush_cb; disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);
  xTaskCreatePinnedToCore(lvgl_tick_task, "lv_tick", 2048, NULL, 1, NULL, 1);
  create_hello_ui();
  ledcWriteTone(BUZZER_CHANNEL, 1200); delay(50); ledcWriteTone(BUZZER_CHANNEL, 0); delay(50);
  ledcWriteTone(BUZZER_CHANNEL, 1600); delay(50); ledcWriteTone(BUZZER_CHANNEL, 0);
}
void loop() {
  lv_timer_handler(); delay(5);
  const uint32_t now = millis();
  for (auto &b : buttons) {
    bool s = digitalRead(b.pin);
    if (s != b.lastState && (now - b.lastChange) > 30) {
      b.lastState = s; b.lastChange = now;
      if (s == LOW) { Serial.printf("Button on GPIO %u\n", b.pin); ledcWriteTone(BUZZER_CHANNEL, 1000); delay(25); ledcWriteTone(BUZZER_CHANNEL, 0); }
    }
  }
}
static void lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
  int32_t w = (area->x2 - area->x1 + 1);
  int32_t h = (area->y2 - area->y1 + 1);
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
  lv_disp_flush_ready(disp_drv);
}
static void lvgl_tick_task(void *) { const TickType_t d = pdMS_TO_TICKS(5); while(true){ lv_tick_inc(5); vTaskDelay(d);} }
static void create_hello_ui() {
  lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x101214), 0);
  lv_obj_t *lbl_time = lv_label_create(lv_scr_act());
  lv_obj_set_style_text_color(lbl_time, lv_color_white(), 0);
  lv_obj_set_style_text_font(lbl_time, &lv_font_montserrat_48, 0);
  lv_label_set_text(lbl_time, "12:34 AM");
  lv_obj_align(lbl_time, LV_ALIGN_LEFT_MID, 8, -10);
  lv_obj_t *lbl_weather = lv_label_create(lv_scr_act());
  lv_obj_set_style_text_color(lbl_weather, lv_palette_main(LV_PALETTE_BLUE), 0);
  lv_obj_set_style_text_font(lbl_weather, &lv_font_montserrat_24, 0);
  lv_label_set_text(lbl_weather, "72°F  " LV_SYMBOL_SUN);
  lv_obj_align(lbl_weather, LV_ALIGN_LEFT_MID, 12, 40);
  lv_obj_t *lbl_status = lv_label_create(lv_scr_act());
  lv_obj_set_style_text_color(lbl_status, lv_color_hex(0xA0A4AB), 0);
  lv_label_set_text(lbl_status, LV_SYMBOL_WIFI "   " LV_SYMBOL_BELL);
  lv_obj_align(lbl_status, LV_ALIGN_BOTTOM_LEFT, 8, -6);
}
static void scan_i2c() {
  Serial.println("I2C scan...");
  uint8_t count = 0;
  for (uint8_t addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    uint8_t err = Wire.endTransmission();
    if (err == 0) { Serial.print(" - Found device at 0x"); Serial.println(addr, HEX); count++; }
  }
  if (count == 0) Serial.println("No I2C devices found. Check SDA/SCL wiring.");
  else Serial.printf("Found %u I2C device(s).\n", count);
}