/*
 * File:   Afficheur.cpp
 * Author: F4GOH
 *
 */

#include "Afficheur.h"

// Constructeur de Afficheur

Afficheur::Afficheur()
{
    tft = new Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

}

Afficheur::~Afficheur() {
    // Rien à nettoyer
}

void Afficheur::begin() {
    // Initialisation I2C avec adresse 0x3C
    Wire.begin();

    if(!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C))
    {
        Serial.println("OLED non detecte");
    }
    else
    {
        Serial.println("OLED OK");
    }

    // Initialisation rétroéclairage TFT
    pinMode(TFT_BL, OUTPUT);
    digitalWrite(TFT_BL, HIGH);

    SPI.setSCK(TFT_SCK);
    SPI.setTX(TFT_MOSI);
    tft->init(172, 320);
    tft->setRotation(1);
    tft->setAddrWindow(34, 0, 172, 320);
    tft->fillScreen(ST77XX_BLACK);
    tft->setTextWrap(false);
    oled.clearDisplay();
}

const uint16_t Afficheur::lineColors[8] = {
    ST77XX_YELLOW,
    ST77XX_CYAN,
    ST77XX_GREEN,
    ST77XX_MAGENTA,
    ST77XX_ORANGE,
    ST77XX_WHITE,
    ST77XX_RED,
    ST77XX_BLUE
};

void Afficheur::timeDisplay(char* txt) {
    tft->setTextSize(4);
    tft->setTextColor(ST77XX_CYAN, ST77XX_BLACK);

    const int width = 172;
    const int height = 22;

    // Efface uniquement la zone du haut
    tft->fillRect(0, 0, width, height, ST77XX_BLACK);

    // Petit padding
    tft->setCursor(46, 0);
    tft->print(txt);

    oledPrint(txt,0,35,1);
}

void Afficheur::modeDisplay(const char* txt) {
    int16_t x, y;
    uint16_t w, h;

    tft->setTextSize(4);
    tft->setTextColor(ST77XX_YELLOW, ST77XX_BLACK);

    tft->getTextBounds(txt, 0, 0, &x, &y, &w, &h);

    const int width = 320;
    const int height = 172;

    // Centrage parfait en portrait
    int cx = (width - w) / 2;
    int cy = (height - h) / 2;

    // Efface uniquement la zone centrale (évite de flinguer le reste)
    int clearY = cy - 4;
    int clearH = h + 8;

    tft->fillRect(0, clearY, width, clearH, ST77XX_BLACK);

    tft->setCursor(cx, cy);
    tft->print(txt);


    // Calcul de la largeur approximative
    int16_t x1, y1;
    oled.getTextBounds(txt, 10, 0, &x1, &y1, &w, &h);

    // centrage horizontal et vertical
    int x0= (128 - w) / 2;
    int y0= (64 - h) / 2;
    oledPrint(txt,40,10,2);
}

void Afficheur::modeEfface() {
    const int width = 172;
    // Zone centrale approximative (même logique que modeDisplay)
    tft->fillRect(0, 120, width, 80, ST77XX_BLACK);

}

void Afficheur::clearDisplay() {
    tft->fillScreen(ST77XX_BLACK);
    oled.fillRect(0, 0, 128, 64, SSD1306_BLACK);
}

void Afficheur::configDisplay(config& cfg) {
    char line[40];

    // Efface uniquement la fenêtre définie
    tft->fillScreen(ST77XX_BLACK);

    tft->setTextSize(2);

    const int x = 0;        // relatif à la fenêtre
    const int lineHeight = 22;

    int y = 10;

    const char * bandStr[7] = {"160m", "80m", "60m", "40m", "30m", "20m", "free frequency"};
    // Ligne 1 : fréquence et offset
    tft->setTextColor(lineColors[0], ST77XX_BLACK);
    snprintf(line, sizeof(line), " f=%lu %ld band %s", cfg.freq, cfg.offset,bandStr[cfg.band]);
    tft->setCursor(x, y);
    tft->print(line);
    y += lineHeight;
    snprintf(line, sizeof(line), "f=%lu %ld %s", cfg.freq, cfg.offset,bandStr[cfg.band]);
    oledPrint(line,0,0,1);

    // Ligne 2
    tft->setTextColor(lineColors[1], ST77XX_BLACK);
    snprintf(line, sizeof(line), "dbm%u every %u minutes", cfg.dbm, cfg.minute);
    tft->setCursor(x, y);
    tft->print(line);
    y += lineHeight;
    oledPrint(line,0,8,1);

    // Ligne 3
    tft->setTextColor(lineColors[2], ST77XX_BLACK);
    snprintf(line, sizeof(line), "gps baud %lu", cfg.baud);
    tft->setCursor(x, y);
    tft->print(line);
    y += lineHeight;
    snprintf(line, sizeof(line), "gps baud %lu wpm %u", cfg.baud,cfg.wpm);
    oledPrint(line,0,16,1);

    // Ligne 4
    tft->setTextColor(lineColors[3], ST77XX_BLACK);
    snprintf(line, sizeof(line), "loc %.4s", cfg.locator);
    tft->setCursor(x, y);
    tft->print(line);
    y += lineHeight;
    oledPrint(line,0,24,1);

    // Ligne 5
    const char* modeStr[] = { "WSPR", "RTTY", "FT8", "HELL", "CW", "IAMBIC", "ALL" };
    tft->setTextColor(lineColors[4], ST77XX_BLACK);
    snprintf(line, sizeof(line), "mode %s %s", modeStr[cfg.mode], cfg.call);
    tft->setCursor(x, y);
    tft->print(line);
    y += lineHeight;


    // Ligne 6
    tft->setTextColor(lineColors[5], ST77XX_BLACK);
    snprintf(line, sizeof(line), "wpm %u nmea %s",
             cfg.wpm,
             cfg.nmeaEnabled ? "on" : "off");
    tft->setCursor(x, y);
    tft->print(line);
    y += lineHeight;
    snprintf(line, sizeof(line), "nmea %s follow %s",
             cfg.nmeaEnabled ? "on" : "off",
             cfg.follow ? "on" : "off");
    oledPrint(line,0,48,1);

    // Ligne 7
    tft->setTextColor(lineColors[6], ST77XX_BLACK);
    snprintf(line, sizeof(line), "Iambic type %c follow %s",
             cfg.bicmd,
             cfg.follow ? "on" : "off");
    tft->setCursor(x, y);
    tft->print(line);
    snprintf(line, sizeof(line), "Iambic type %c",
             cfg.bicmd);
    oledPrint(line,0,56,1);
}

void Afficheur::printCharCW(char car) {

    if (firstChar) {
       // tft->fillScreen(ST77XX_BLACK);
         tft->fillRect(
        0,
        CHAR_HEIGHT * 1,                         // début à la ligne 1
        SCREEN_HEIGHT,
        CHAR_HEIGHT * (MAX_LINES - 1),           // hauteur des lignes 1 à 4
        ST77XX_BLACK
    );

        tft->setTextSize(TEXT_SIZE);
        tft->setTextWrap(false);

        currentCol = 0;
        currentLine = 1;
        firstChar = false;
    }

    // retour ligne AVANT écriture
    if (currentCol >= MAX_COLS) {
        currentCol = 0;
        currentLine++;
    }

    // écran plein
    if (currentLine >= MAX_LINES) {
        //tft->fillScreen(ST77XX_BLACK);

    tft->fillRect(
        0,
        CHAR_HEIGHT * 1,                         // début à la ligne 1
        SCREEN_HEIGHT,
        CHAR_HEIGHT * (MAX_LINES - 1),           // hauteur des lignes 1 à 4
        ST77XX_BLACK
    );

        currentLine = 1;
    }

    int x = currentCol * CHAR_WIDTH;
    int y = currentLine * CHAR_HEIGHT;

    // 🔥 couleur selon la ligne
    uint16_t color = lineColors[currentLine % (sizeof(lineColors) / sizeof(lineColors[0]))];
    tft->setTextColor(color, ST77XX_BLACK);

    tft->setCursor(x, y);
    tft->write(car);

    currentCol++;
}


void Afficheur::printFrequency(uint32_t freq) {

    char buf[16];
    snprintf(buf, sizeof(buf), "%lu", freq);

    uint16_t color = lineColors[0];

    tft->setTextSize(TEXT_SIZE);
    tft->setTextWrap(false);
    tft->setTextColor(color, ST77XX_BLACK);

    // position ligne 0
    int x = 20;
    int y = 0;

    tft->setCursor(x, y);
    tft->print(buf);
    oledPrint(buf,10,0,1);
}

void Afficheur::oledPrint(String txt, int x , int y , int Size)
{
    //oled.clearDisplay();
    // Calculer la largeur et la hauteur du texte précédent
    int textWidth = txt.length() * 6 * Size;  // Largeur approximative (6 pixels par caractère)
    int textHeight = 8 * Size;                     // Hauteur approximative (8 pixels par taille)
    oled.fillRect(x, y, textWidth, textHeight, SSD1306_BLACK);
    oled.setTextSize(Size);              // taille du texte
    oled.setTextColor(SSD1306_WHITE);  // Couleur du texte (blanc pour OLED)
    oled.setCursor(x, y);
    oled.println(txt);
    oled.display();

    // Effacer l'écran
    //oled.clearDisplay();

}
