#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <U8g2_for_Adafruit_GFX.h>
#include "init.h"
#include "ui.h"
#include "utils.h"
#include "ad7606.h"

U8G2_FOR_ADAFRUIT_GFX u8g2;  // 给 Adafruit_GFX 套一层 U8g2 的“文字引擎”
using namespace esp32;

#define TFT_MOSI 16
#define TFT_SCLK 15
#define TFT_CS 18
#define TFT_DC 17
#define TFT_RST -1

// 屏幕尺寸为 128x160
Adafruit_ST7735 tft(TFT_CS, TFT_DC, TFT_RST);

using namespace esp32::utils;
using namespace esp32::ui;

const int BTN_LEFT = 12;   // 左按钮
const int BTN_RIGHT = 11;  // 右按钮
const int BTN_UP = 10;     // 上按钮

// 颜色宏兼容已由 utils.h 提供

// 应用状态
struct AppState {
    // 环形缓冲：宽度=屏幕宽；时间窗口=3秒
    static const int GraphW = 128; // 与屏幕宽度一致
    int16_t samples[GraphW];
    int writeIdx = 0;        // 下一个写入位置
    int sampleCount = 0;     // 已写入样本（<=GraphW）
    int16_t lastRaw = 0;     // 最新原始码
    uint32_t lastSampleMs = 0; // 上一次采样时间
    static const uint32_t WindowMs = 3000; // 3 秒窗口
    static const uint32_t SampleIntervalMs = WindowMs / GraphW; // 约 23ms
};

static UI appUI;
static AppState app;

static bool prevLeft = false;
static bool prevRight = false;
static bool prevUp = false;

// 布局参数
static const int SCREEN_W = 128;
static const int SCREEN_H = 160;
static const int ICON_W = 48;   // 图标宽度
static const int ICON_H = 48;   // 图标高度
static const int SPACING = 72;  // 图标中心间距（略大于宽度，保证边缘留白）
static const int CENTER_X = (SCREEN_W - ICON_W) / 2;  // 中心图标左上角 X
static const int BASE_Y = 40;       // 图标顶端 Y（上方留空间给标题）
static const int LABEL_MARGIN = 12;  // 图标与文字竖向间距

static const int CHAR_W = 14;
static const int CHAR_H = 14;

// 工具：推入一条新样本（原码）
static inline void pushSample(AppState& s, int16_t code, uint32_t nowMs) {
    // 控制写入速率，保持一屏=3秒
    if (nowMs - s.lastSampleMs < AppState::SampleIntervalMs) return;
    s.lastSampleMs = nowMs;
    s.samples[s.writeIdx] = code;
    s.writeIdx = (s.writeIdx + 1) % AppState::GraphW;
    if (s.sampleCount < AppState::GraphW) s.sampleCount++;
    s.lastRaw = code;
}

// 根据状态输出显示列表
static void buildScene(void* ctx, DisplayList& out) {
    auto* st = static_cast<AppState*>(ctx);

    // 背景整屏清除
    out.addFillRect(1, 0, 0, SCREEN_W, SCREEN_H, BLACK);

    // 显示当前原始码（居中顶部，去掉电压）
    char line[48];
    snprintf(line, sizeof(line), "CH0: %d", st->lastRaw);
    out.addText(2, SCREEN_W / 2, 10, WHITE, line, true);

    // 图形区域：最大化剩余高度，无边框
    const int topY = 24; // 标题高度
    const int graphH = SCREEN_H - topY; // 剩余高度
    const int gw = AppState::GraphW; // 128
    const int gx = 0;

    if (st->sampleCount == 0) return; // 尚无数据

    // 动态范围（min-200, max+200）
    int16_t minV = st->samples[0];
    int16_t maxV = st->samples[0];
    for (int i = 1; i < st->sampleCount; ++i) {
        int16_t v = st->samples[i];
        if (v < minV) minV = v;
        if (v > maxV) maxV = v;
    }
    int32_t rangeMin = (int32_t)minV - 200;
    int32_t rangeMax = (int32_t)maxV + 200;
    if (rangeMin < -32768) rangeMin = -32768;
    if (rangeMax > 32767) rangeMax = 32767;
    int32_t span = rangeMax - rangeMin;
    if (span <= 0) span = 1;

    auto mapY = [&](int16_t code) -> int {
        float rel = (float)((int32_t)code - rangeMin) / (float)span; // 0..1
        if (rel < 0.0f) rel = 0.0f; if (rel > 1.0f) rel = 1.0f;
        float y = (1.0f - rel) * (graphH - 1); // 倒置
        int iy = topY + (int)(y + 0.5f);
        if (iy < topY) iy = topY;
        if (iy > topY + graphH - 1) iy = topY + graphH - 1;
        return iy;
    };

    int prevY = mapY(st->samples[(st->writeIdx) % gw]);
    for (int x = 1; x < gw; ++x) {
        int idx = (st->writeIdx + x) % gw;
        int y = mapY(st->samples[idx]);
        out.addLine(100 + x, gx + x - 1, prevY, gx + x, y, GREEN);
        prevY = y;
    }
}

void setup() {
    // 按钮:内部下拉
    pinMode(BTN_LEFT, INPUT_PULLDOWN);
    pinMode(BTN_RIGHT, INPUT_PULLDOWN);
    pinMode(BTN_UP, INPUT_PULLDOWN);

    // 1. 把硬件 SPI 绑定到现有的引脚（与 AD7606 共用：MISO=AD7606 DOUTA）
    SPI.begin(TFT_SCLK, ad7606::PIN_AD_MISO, TFT_MOSI, TFT_CS);
    SPI.setFrequency(27000000);  // ST7735 通常 27MHz 左右比较稳

    // 2. 初始化屏幕
    tft.initR(INITR_GREENTAB);
    tft.setRotation(0);
    tft.fillScreen(BLACK);
    tft.setCursor(0, 0);
    // ★ 关键：把 u8g2 挂到 tft 上
    u8g2.begin(tft);
    // 连接到 Adafruit_GFX :contentReference[oaicite:2]{index=2}
    u8g2.setFontMode(1);                    // 透明背景（默认也是 1）
    u8g2.setFontDirection(0);               // 正常从左到右
    u8g2.setForegroundColor(WHITE);  // 文字颜色

    // 使用更小的中文字体
    // u8g2_font_wqy12_t_chinese1: 12像素，常用汉字（约2500字）
    // u8g2_font_wqy12_t_chinese2: 12像素，更多汉字（约6000字）
    // u8g2_font_wqy12_t_chinese3: 12像素，完整汉字（约9000字）
    u8g2.setFont(u8g2_font_wqy12_t_chinese3);  // 12像素字体，比 unifont 小

    tft.setTextColor(WHITE);
    tft.setTextSize(1);

    // 初始化系统(读取配置并连接 WiFi)
    init::initSystem(tft);

    // UI 初始化，传入 u8g2 以支持中文
    appUI.begin(&tft, &u8g2);
    // 启用内存帧缓冲，避免闪烁（若内存不足会返回 false）
    appUI.enableBackBuffer(SCREEN_W, SCREEN_H);

    // 绑定场景构建器
    appUI.setScene(buildScene, &app);

    // 初始化 AD7606（与 TFT 共用 SPI）
    ad7606::init();

    // 清空波形缓存并初始化计时
    for (int i = 0; i < AppState::GraphW; ++i) app.samples[i] = 0;
    app.sampleCount = 0;
    app.lastSampleMs = millis();
}

void loop() {
    bool leftPressed = digitalRead(BTN_LEFT) == HIGH;  // 按下=HIGH
    bool rightPressed = digitalRead(BTN_RIGHT) == HIGH;
    bool upPressed = digitalRead(BTN_UP) == HIGH;

    // 读取 AD7606 CH0 原始码并按速率写入缓冲
    uint32_t now = millis();
    int16_t ch0 = ad7606::readCH0();
    pushSample(app, ch0, now);

    // 驱动 UI 帧刷新
    appUI.tick(millis());


    delay(16);  // 简单节流 ~60FPS
}
