#include <Wire.h>
#include <hd44780.h>                        // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h>  // i2c expander i/o class header
#include "RTClib.h"
#include "Sonde.h"

// LE LCD
const uint8_t nbColonnes = 20;
const uint8_t nbLignes = 4;
hd44780_I2Cexp lcd;

byte barre[] = {0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100};
byte coeur[] = {0b00000, 0b01010, 0b11111, 0b11111, 0b01110, 0b00100, 0b00000, 0b00000};
byte skull[] = {0b00000, 0b01110, 0b10101, 0b11011, 0b01110, 0b01110, 0b00000, 0b00000};

// la RTC
RTC_DS1307 rtc;

// Les sondes
Sonde sondes[] = {
  { 6, "S1"},
  { 7, "S2"},
  { 8, "S3"},
  { 9, "S4"},
};
constexpr size_t nombreDeSondes = sizeof sondes / sizeof * sondes;

const byte tailleMaxTxt = 10;
char affichageTemperature[nombreDeSondes][tailleMaxTxt];
char affichageHeure[9];

void afficherTemperatures() {
  // on met à jour les températures
  char tmpTxt[tailleMaxTxt];
  for (byte i = 0; i < nombreDeSondes; i++) {
    dtostrf(sondes[i].temperature(), 1, 1, tmpTxt); // conversion en chaîne de caractères
    if (strcmp(tmpTxt, affichageTemperature[i]) != 0) {
      // le texte a changé on effectue le nouvel affichage
      lcd.setCursor(0, i);
      lcd.print(sondes[i].nom);
      lcd.print(": ");
      lcd.print(tmpTxt);
      lcd.write(0xDF); // ° symbol
      if (strlen(tmpTxt) < strlen(affichageTemperature[i])) {
        // le nouveau texte est plus court que l'ancien, on efface les caractères en trop
        for (byte i = 0; i < strlen(affichageTemperature[i]) - strlen(tmpTxt); i++) lcd.write(' ');
      }
      strcpy(affichageTemperature[i], tmpTxt); // on mémorise ce qui est affiché
    }
  }
}

void afficherHeure() {
  DateTime now = rtc.now();
  char heureTxt[9];
  sprintf(heureTxt, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  if (strcmp(affichageHeure, heureTxt) != 0) {
    // l'heure a changée, on effectue l'affichage
    lcd.setCursor(nbColonnes - 8, 0);
    lcd.print(heureTxt);
    strcpy(affichageHeure, heureTxt); // on mémorise ce qui est affiché
  }
}

void blink() {
  static unsigned long chrono = -500;
  static byte symbole = 0; // le coeur, 1 le crane
  if (millis() - chrono >= 500) {
    lcd.setCursor(nbColonnes - 1, nbLignes - 1); // en bas à droite
    lcd.write(symbole);
    symbole = 1 - symbole; // on passe à l'autre symbole
    chrono = millis();
  }
}

void setup() {
  for (Sonde& s : sondes) s.begin();
  Serial.begin(115200);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }
  int result = lcd.begin(nbColonnes, nbLignes);
  if (result) {
    Serial.print("LCD initialization failed: ");
    Serial.println(result);
    hd44780::fatalError(result);
  }
  lcd.createChar(0, coeur);
  lcd.createChar(1, skull);
  lcd.createChar(2, barre);

  // on dessine la barre de séparation
  for (byte i = 0; i < nbLignes; i++) {
    lcd.setCursor(nbColonnes - 9, i);
    lcd.write(2);
  }

}

void loop() {
  afficherTemperatures();
  afficherHeure();
  blink(); // pour montrer qu'on peut faire autre chose du moment que c'est non bloquant
}
GND5VSDASCLSQWRTCDS1307+
Sonde 4
Sonde 3
Sonde 2
Sonde 1