#include "display.h"
#include "config.h"
#include <U8g2lib.h>
#include <Wire.h>

static U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
static uint32_t s_lastUpdateMs = 0;

static bool throttled() {
    return (millis() - s_lastUpdateMs) < DISPLAY_UPDATE_MS;
}

static void markUpdated() {
    s_lastUpdateMs = millis();
}

static void drawSep(uint8_t y) {
    u8g2.drawHLine(0, y, OLED_W);
}

// Truncate src to maxChars and copy to dst (dst must have maxChars+1 bytes)
static void trunc(const char* src, char* dst, uint8_t maxChars) {
    strncpy(dst, src, maxChars);
    dst[maxChars] = '\0';
}

// Draw text centered horizontally at top-position y
static void drawCentered(uint8_t y, const char* str) {
    uint8_t w = u8g2.getStrWidth(str);
    u8g2.drawStr((OLED_W - w) / 2, y, str);
}

// ── Publiczne API ─────────────────────────────────────────────────────────────

void display_init() {
    Wire.begin();
    u8g2.begin();
    u8g2.setFontPosTop();          // Y = górna krawędź znaku
    u8g2.setContrast(200);
    u8g2.clearBuffer();
    u8g2.sendBuffer();
}

void display_force_update() {
    s_lastUpdateMs = 0;
}

void display_show_splash() {
    u8g2.clearBuffer();

    // Tytuł — większy font, wycentrowany
    u8g2.setFont(u8g2_font_8x13_tf);
    drawCentered(4, "CNC Draw");

    // Wersja — mniejszy font
    u8g2.setFont(u8g2_font_6x10_tf);
    drawCentered(21, "v." FIRMWARE_VERSION);

    drawSep(35);

    drawCentered(40, FIRMWARE_AUTHOR);

    u8g2.sendBuffer();
    delay(2000);
    markUpdated();
}

void display_show_homing() {
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);
    drawCentered(0, "Kalibracja...");
    drawSep(13);
    drawCentered(22, "Szukam pozycji 0,0");
    u8g2.setFont(u8g2_font_5x7_tf);
    drawCentered(40, "Prosze czekac...");
    u8g2.sendBuffer();
    markUpdated();
}

void display_show_main_menu(uint8_t selected) {
    if (throttled()) return;
    markUpdated();

    static const char* const items[3] = {"Drukowanie", "Tryb UART", "Test osi"};

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    drawCentered(0, "CNC Draw - Menu");
    drawSep(12);

    for (uint8_t i = 0; i < 3; i++) {
        uint8_t yTop = 14 + i * 17;
        if (i == selected) {
            u8g2.setDrawColor(1);
            u8g2.drawBox(0, yTop - 1, OLED_W, 13);
            u8g2.setDrawColor(0);
            u8g2.drawStr(4, yTop, items[i]);
            u8g2.setDrawColor(1);
        } else {
            u8g2.drawStr(4, yTop, items[i]);
        }
    }

    u8g2.sendBuffer();
}

void display_show_axis_test(char axis, float posX, float posY, bool limitHit) {
    if (throttled()) return;
    markUpdated();

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    if (limitHit) {
        drawCentered(0, "! KRANC OW KA !");
        drawSep(12);
        drawCentered(20, "Cofanie...");
        u8g2.setFont(u8g2_font_5x7_tf);
        drawCentered(38, "czekaj");
    } else {
        char hdr[22];
        snprintf(hdr, sizeof(hdr), "Test osi: %c", axis);
        u8g2.drawStr(0, 0, hdr);
        drawSep(12);

        char buf[22];
        snprintf(buf, sizeof(buf), "X: %5.1f mm", posX);
        u8g2.drawStr(0, 14, buf);
        snprintf(buf, sizeof(buf), "Y: %5.1f mm", posY);
        u8g2.drawStr(0, 27, buf);

        drawSep(42);
        u8g2.setFont(u8g2_font_5x7_tf);
        u8g2.drawStr(0, 46, "UP/DOWN = ruch");
        u8g2.drawStr(0, 55, "OK = zmien os");
    }

    u8g2.sendBuffer();
}

void display_show_file_list(const char files[][FILENAME_MAX_LEN], uint8_t count, uint8_t selected) {
    if (throttled()) return;
    markUpdated();

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    if (count == 0) {
        drawCentered(16, "Brak plikow");
        drawCentered(30, ".gcode na SD");
        u8g2.sendBuffer();
        return;
    }

    // Nagłówek z licznikiem
    char hdr[22];
    snprintf(hdr, sizeof(hdr), "Pliki [%d/%d]", selected + 1, count);
    u8g2.drawStr(0, 0, hdr);
    drawSep(12);

    // 4 wpisy plików (Y = 14, 27, 40, 53)
    uint8_t scrollOffset = (selected / 4) * 4;
    for (uint8_t i = 0; i < 4 && (scrollOffset + i) < count; i++) {
        uint8_t idx  = scrollOffset + i;
        uint8_t yTop = 14 + i * 13;

        char fname[22];
        trunc(files[idx], fname, 21);

        if (idx == selected) {
            // Wybrany element — odwrócone tło
            u8g2.setDrawColor(1);
            u8g2.drawBox(0, yTop - 1, OLED_W, 13);
            u8g2.setDrawColor(0);
            u8g2.drawStr(3, yTop, fname);
            u8g2.setDrawColor(1);
        } else {
            u8g2.drawStr(3, yTop, fname);
        }
    }

    u8g2.sendBuffer();
}

void display_show_printing(const char* filename, uint8_t percent, float speedMult) {
    if (throttled()) return;
    markUpdated();

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    // Nagłówek: "DRUKOWANIE" + procent
    u8g2.drawStr(0, 0, "DRUKOWANIE");
    char pct[8];
    snprintf(pct, sizeof(pct), "%d%%", percent);
    uint8_t pw = u8g2.getStrWidth(pct);
    u8g2.drawStr(OLED_W - pw, 0, pct);
    drawSep(12);

    // Nazwa pliku (max 21 znaków)
    char fname[22];
    trunc(filename, fname, 21);
    u8g2.drawStr(0, 14, fname);

    // Pasek postępu (ramka + wypełnienie)
    u8g2.drawFrame(0, 28, OLED_W, 10);
    uint8_t fill = (uint8_t)((uint32_t)(OLED_W - 2) * percent / 100);
    if (fill > 0) u8g2.drawBox(1, 29, fill, 8);

    // Prędkość
    int mi = (int)(speedMult * 10);
    char spd[22];
    snprintf(spd, sizeof(spd), "Predkosc: %d.%dx", mi / 10, mi % 10);
    u8g2.drawStr(0, 42, spd);

    u8g2.sendBuffer();
}

void display_show_confirm_stop(bool yesSelected) {
    if (throttled()) return;
    markUpdated();

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    drawCentered(2, "Przerwac druk?");
    drawSep(14);

    // Przycisk TAK (lewy)
    if (yesSelected) {
        u8g2.drawBox(8, 26, 50, 18);
        u8g2.setDrawColor(0);
        u8g2.drawStr(21, 30, "TAK");
        u8g2.setDrawColor(1);
    } else {
        u8g2.drawFrame(8, 26, 50, 18);
        u8g2.drawStr(21, 30, "TAK");
    }

    // Przycisk NIE (prawy)
    if (!yesSelected) {
        u8g2.drawBox(70, 26, 50, 18);
        u8g2.setDrawColor(0);
        u8g2.drawStr(83, 30, "NIE");
        u8g2.setDrawColor(1);
    } else {
        u8g2.drawFrame(70, 26, 50, 18);
        u8g2.drawStr(83, 30, "NIE");
    }

    // Podpowiedź
    u8g2.setFont(u8g2_font_5x7_tf);
    drawCentered(52, "UP/DOWN=wybor  OK=ok");

    u8g2.sendBuffer();
}

void display_show_uart_mode() {
    if (throttled()) return;
    markUpdated();

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    drawCentered(0, "TRYB UART");
    drawSep(12);

    u8g2.drawStr(4, 18, "Wysylaj komendy GCode");
    u8g2.drawStr(4, 31, "przez port szeregowy");
    u8g2.drawStr(4, 44, "115200 baud");

    u8g2.sendBuffer();
}

void display_show_error(const char* line1, const char* line2) {
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tf);

    u8g2.drawStr(0, 0, "! BLAD");
    drawSep(12);

    if (line1) u8g2.drawStr(0, 15, line1);
    if (line2) u8g2.drawStr(0, 28, line2);

    drawSep(42);
    u8g2.setFont(u8g2_font_5x7_tf);
    drawCentered(46, "Nacisnij OK");
    drawCentered(55, "aby kontynuowac");

    u8g2.sendBuffer();
    markUpdated();
}
