#include "ui.h"
#include "utils.h"

namespace esp32 {
namespace ui {

using namespace esp32::utils;

bool UI::loadIconFromFS(const char* path, Icon& out) {
    File f = LittleFS.open(path, "r");
    if (!f) {
        return false;
    }
    if (f.size() < 4) {
        f.close();
        return false;
    }
    uint8_t hdr[4];
    if (f.read(hdr, 4) != 4) {
        f.close();
        return false;
    }
    uint16_t w = hdr[0] | (hdr[1] << 8);
    uint16_t h = hdr[2] | (hdr[3] << 8);
    size_t count = (size_t)w * (size_t)h;
    size_t bytes = count * 2;
    if (f.size() < 4 + bytes) {
        f.close();
        return false;
    }
    uint16_t* buf = (uint16_t*)malloc(bytes);
    if (!buf) {
        f.close();
        return false;
    }
    // 文件内为 RGB565，小端，每像素2字节
    size_t read = f.read((uint8_t*)buf, bytes);
    f.close();
    if (read != bytes) {
        free(buf);
        return false;
    }
    out.width = w;
    out.height = h;
    out.pixels = buf;
    return true;
}

void UI::freeIcon(Icon& icon) {
    if (icon.pixels) {
        free(icon.pixels);
        icon.pixels = nullptr;
    }
    icon.width = icon.height = 0;
}

int UI::addTweenFloat(float* target, float to, uint32_t durationMs,
                      float x1, float y1, float x2, float y2) {
    for (int i = 0; i < MAX_TWEENS; ++i) {
        if (!_tweens[i].active) {
            _tweens[i].target = target;
            _tweens[i].from = *target;
            _tweens[i].to = to;
            _tweens[i].startMs = millis();
            _tweens[i].durationMs = durationMs;
            _tweens[i].x1 = x1; _tweens[i].y1 = y1; _tweens[i].x2 = x2; _tweens[i].y2 = y2;
            _tweens[i].active = true;
            return i;
        }
    }
    return -1;
}

bool UI::hasActiveTweens() const {
    for (int i = 0; i < MAX_TWEENS; ++i) {
        if (_tweens[i].active) return true;
    }
    return false;
}

bool UI::isTweenActive(int id) const {
    if (id < 0 || id >= MAX_TWEENS) return false;
    return _tweens[id].active;
}

void UI::_updateTweens(uint32_t nowMs) {
    for (int i = 0; i < MAX_TWEENS; ++i) {
        Tween& t = _tweens[i];
        if (!t.active) continue;
        uint32_t elapsed = nowMs - t.startMs;
        float p = 0.0f;
        if (elapsed >= t.durationMs) {
            p = 1.0f;
        } else {
            p = (float)elapsed / (float)t.durationMs;
        }
        float eased = linear2CubicBezier(p, t.x1, t.y1, t.x2, t.y2);
        *t.target = t.from + (t.to - t.from) * eased;
        if (p >= 1.0f) {
            *t.target = t.to;
            t.active = false;
        }
    }
}

void UI::_drawIcon(int16_t x, int16_t y, const Icon& icon) {
    if (!_tft || !icon.pixels) return;
    // 使用 Adafruit_GFX 的批量位图绘制，显著快于逐像素
    _tft->drawRGBBitmap(x, y, icon.pixels, icon.width, icon.height);
}

void UI::_render(const DisplayList& list) {
    if (!_tft) return;
    if (_useBackBuffer) {
        _renderToCanvas(list);
        _flushCanvas();
        _swapCanvas();
        return;
    }
    // 无缓冲模式：清屏 + 重放
    _tft->fillScreen(BLACK);
    _tft->setTextWrap(false);
    for (int i = 0; i < list.size(); ++i) {
        const auto& it = list.at(i);
        switch (it.op) {
            case OpType::FillRect:
                _tft->fillRect(it.x, it.y, it.w, it.h, it.color);
                break;
            case OpType::DrawText:
                if (it.text) {
                    int16_t x = it.x;
                    int16_t y = it.y;
                    // 使用 U8g2 渲染中文（如果可用）
                    if (_u8g2) {
                        // 如果需要居中 (w=1)，计算实际文本宽度
                        if (it.w == 1) {
                            int16_t textWidth = _u8g2->getUTF8Width(it.text);
                            x = x - textWidth / 2;
                        }
                        // U8g2 使用基线坐标系，需要加上字体上升高度
                        int16_t ascent = _u8g2->getFontAscent();
                        _u8g2->setForegroundColor(it.color);
                        _u8g2->setCursor(x, y + ascent);
                        _u8g2->print(it.text);
                    } else {
                        // 降级到 Adafruit GFX
                        if (x >= 0 && x < _tft->width()) {
                            _tft->setCursor(x, y);
                            _tft->setTextColor(it.color);
                            _tft->print(it.text);
                        }
                    }
                }
                break;
            case OpType::DrawIcon:
                if (it.icon) _drawIcon(it.x, it.y, *it.icon);
                break;
            case OpType::Line:
                _tft->drawLine(it.x, it.y, it.w, it.h, it.color);
                break;
            case OpType::Circle:
                _tft->drawCircle(it.x, it.y, it.w, it.color);
                break;
        }
    }
}

bool UI::enableBackBuffer(uint16_t width, uint16_t height) {
    if (_useBackBuffer) return true; // already enabled
    _bufW = width;
    _bufH = height;
    _canvasA = new GFXcanvas16(width, height);
    _canvasB = new GFXcanvas16(width, height);
    if (!_canvasA || !_canvasB) {
        delete _canvasA; _canvasA = nullptr;
        delete _canvasB; _canvasB = nullptr;
        return false;
    }
    _canvasA->fillScreen(BLACK);
    _canvasB->fillScreen(BLACK);
    _canvasCurrent = _canvasA;
    _canvasPrev = _canvasB;
    _useBackBuffer = true;
    return true;
}

void UI::_renderToCanvas(const DisplayList& list) {
    if (!_canvasCurrent) return;
    _canvasCurrent->fillScreen(BLACK);
    _canvasCurrent->setTextWrap(false);
    for (int i = 0; i < list.size(); ++i) {
        const auto& it = list.at(i);
        switch (it.op) {
            case OpType::FillRect:
                _canvasCurrent->fillRect(it.x, it.y, it.w, it.h, it.color);
                break;
            case OpType::DrawText:
                if (it.text) {
                    int16_t x = it.x;
                    int16_t y = it.y;
                    // 使用 U8g2 渲染中文（如果可用）
                    // 注意：U8g2 需要先临时切换到画布，渲染后再切回屏幕
                    if (_u8g2) {
                        // 暂时将 U8g2 指向画布
                        _u8g2->begin(*_canvasCurrent);
                        // 如果需要居中 (w=1)，计算实际文本宽度
                        if (it.w == 1) {
                            int16_t textWidth = _u8g2->getUTF8Width(it.text);
                            x = x - textWidth / 2;
                        }
                        // U8g2 使用基线坐标系，需要加上字体上升高度
                        int16_t ascent = _u8g2->getFontAscent();
                        _u8g2->setForegroundColor(it.color);
                        _u8g2->setCursor(x, y + ascent);
                        _u8g2->print(it.text);
                        // 恢复到屏幕
                        _u8g2->begin(*_tft);
                    } else {
                        // 降级到 Adafruit GFX
                        if (x >= 0 && x < _bufW) {
                            _canvasCurrent->setCursor(x, y);
                            _canvasCurrent->setTextColor(it.color);
                            _canvasCurrent->print(it.text);
                        }
                    }
                }
                break;
            case OpType::DrawIcon:
                if (it.icon && it.icon->pixels) {
                    // 在画布上绘制位图
                    _canvasCurrent->drawRGBBitmap(it.x, it.y, it.icon->pixels, it.icon->width, it.icon->height);
                }
                break;
            case OpType::Line:
                _canvasCurrent->drawLine(it.x, it.y, it.w, it.h, it.color);
                break;
            case OpType::Circle:
                _canvasCurrent->drawCircle(it.x, it.y, it.w, it.color);
                break;
        }
    }
}

void UI::_flushCanvas() {
    if (!_tft || !_canvasCurrent) return;
    // 初版：整帧推送，避免闪烁；后续可做 diff 行段优化
    _tft->drawRGBBitmap(0, 0, _canvasCurrent->getBuffer(), _bufW, _bufH);
}

void UI::_swapCanvas() {
    // 交换当前与前一帧（为后续行 diff 做准备）
    GFXcanvas16* tmp = _canvasPrev;
    _canvasPrev = _canvasCurrent;
    _canvasCurrent = tmp;
}

void UI::tick(uint32_t nowMs) {
    _updateTweens(nowMs);
    _list.clear();
    if (_builder) {
        _builder(_builderCtx, _list);
    }
    _render(_list);
}

}  // namespace ui
}  // namespace esp32
