#include <SPI.h>
#include <GxEPD2_BW.h>
#include <WiFi.h>
#include <time.h>
#include "logo_ilm.h"

// Branchement : VCC=3V3, GND=GND, DIN=23, CLK=18,
// CS=27, DC=26, RST=25, BUSY=33.
// Essai du pilote historique Waveshare 1.54 pouces noir/blanc V1.
using Panel = GxEPD2_154;
// Pour une dalle V2 : utiliser GxEPD2_154_D67.
GxEPD2_BW<Panel, Panel::HEIGHT> display(Panel(27, 26, 25, 33));

// Facultatif : renseigner le Wi-Fi pour obtenir l'heure exacte.
const char* WIFI_SSID = "";
const char* WIFI_PASSWORD = "";
float temperatureDemo = 20.0;
int humiditeDemo = 50;
unsigned int etapeSimulation = 0;
unsigned long dernierAffichage;

void texteCentre(const String& texte, int x, int y, int w, int h, int taille) {
  display.setTextSize(taille);
  int16_t bx, by;
  uint16_t tw, th;
  display.getTextBounds(texte, 0, 0, &bx, &by, &tw, &th);
  display.setCursor(x + (w - (int)tw) / 2 - bx,
                    y + (h - (int)th) / 2 - by);
  display.print(texte);
}

void initialiserHeure() {
  setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
  tzset();
  // Sans Wi-Fi : horloge initialisee a la date et heure de compilation.
  char mois[4];
  int jour, annee, heure, minute, seconde;
  sscanf(__DATE__, "%3s %d %d", mois, &jour, &annee);
  sscanf(__TIME__, "%d:%d:%d", &heure, &minute, &seconde);
  const char* noms = "JanFebMarAprMayJunJulAugSepOctNovDec";
  const char* position = strstr(noms, mois);
  struct tm date = {};
  date.tm_year = annee - 1900;
  date.tm_mon = position ? (position - noms) / 3 : 0;
  date.tm_mday = jour;
  date.tm_hour = heure;
  date.tm_min = minute;
  date.tm_sec = seconde;
  date.tm_isdst = -1;
  struct timeval tv = {mktime(&date), 0};
  settimeofday(&tv, nullptr);
  if (strlen(WIFI_SSID)) {
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    unsigned long debut = millis();
    while (WiFi.status() != WL_CONNECTED && millis() - debut < 15000) delay(100);
    if (WiFi.status() == WL_CONNECTED) {
      configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "pool.ntp.org", "time.nist.gov");
      delay(2000);
    }
  }
}

void afficher() {
  time_t maintenant = time(nullptr);
  struct tm date;
  localtime_r(&maintenant, &date);
  char annee[8], dateTexte[16], heureTexte[8];
  strftime(annee, sizeof(annee), "%Y", &date);
  strftime(dateTexte, sizeof(dateTexte), "%d/%m/%Y", &date);
  strftime(heureTexte, sizeof(heureTexte), "%H:%M", &date);
  display.setFullWindow();
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    display.setTextColor(GxEPD_BLACK);
    display.setTextWrap(false);
    display.drawRect(0, 0, 200, 200, GxEPD_BLACK);
    for (int y : {36, 76, 116, 158}) display.drawFastHLine(0, y, 200, GxEPD_BLACK);
    display.drawFastVLine(88, 0, 116, GxEPD_BLACK);
    display.drawBitmap(4, 4, LOGO_ILM, 80, 28, GxEPD_BLACK);
    texteCentre(annee, 89, 1, 110, 35, 3);
    texteCentre("Tmp", 1, 37, 86, 39, 3);
    String temperature = String(temperatureDemo, 1) + " C";
    texteCentre(temperature, 89, 37, 110, 39, 2);
    // Petit cercle pour le symbole degre, au-dessus de l'espace avant C.
    display.drawCircle(161, 49, 2, GxEPD_BLACK);
    texteCentre("Humi", 1, 77, 86, 39, 2);
    texteCentre(String(humiditeDemo) + "%HR", 89, 77, 110, 39, 2);
    texteCentre(dateTexte, 1, 117, 198, 41, 2);
    texteCentre(heureTexte, 1, 159, 198, 40, 4);
  } while (display.nextPage());
  display.hibernate();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Demarrage tableau - pilote Waveshare V1");
  SPI.begin(18, -1, 23, 27);
  display.init(115200, true, 2, false);
  initialiserHeure();
  afficher();
  dernierAffichage = millis();
  Serial.println("Tableau affiche. Temperature et humidite : demonstration.");
}

void loop() {
  if (millis() - dernierAffichage >= 60000) {
    // Variations lentes de demonstration : 18 a 22 C, 45 a 55 %HR.
    ++etapeSimulation;
    temperatureDemo = 20.0 + 2.0 * sin(etapeSimulation * 0.25);
    humiditeDemo = 50 + (int)round(5.0 * sin(etapeSimulation * 0.18));
    afficher();
    dernierAffichage = millis();
  }
  delay(100);
}
