#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>

#define UL unsigned long
#define DHTTYPE DHT22
#define DHT_PIN 7
#define BUTTON_PIN 8
#define EEPROM_ADDR 0
#define FPS 5

UL prev = 0, last_update = 0, last_press = 0;
int record = 0;
float temperature, humidity, vals[4];
LiquidCrystal_I2C lcd(0x27,16,2);
DHT dht(DHT_PIN, DHTTYPE);

byte grau[8] = {0b00110, 0b01001, 0b01001, 0b00110,
                0b00000, 0b00000, 0b00000, 0b00000};
byte setaBaixo[8] = {0b00000, 0b00100, 0b00100, 0b00100,
                     0b10101, 0b01110, 0b00100, 0b00000};
byte setaCima[8] = {0b00000, 0b00100, 0b01110, 0b10101,
                   0b00100, 0b00100, 0b00100, 0b00000};

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(A0, INPUT);
  lcd.init();
  lcd.backlight();
  lcd.createChar(0, grau);
  lcd.createChar(1, setaBaixo);
  lcd.createChar(2, setaCima);
  dht.begin();
  initialize();
}

void loop() {
  UL now = millis();
  if (now - last_update > 2000) { // DHT update rate 2s (0.5hz)?
    temperature = dht.readTemperature();
    humidity = dht.readHumidity();
    checkChanges();
    last_update = now;
  }

  if (record == 1) { temperature = vals[0]; humidity = vals[2]; }
  else if (record == 2) { temperature = vals[1]; humidity = vals[3]; }

  if (digitalRead(BUTTON_PIN) == LOW) {
    if (now - last_press > 500) {
      record = (record + 1 > 2) ? 0 : record + 1;
    }
    last_press = now;
  }

  if (now - prev > (1000 / FPS)) { // Screen rate
    printScreen();
    prev = now;
  }
}

void initialize() {
  for (int i = 0; i < 4; i++) {
    EEPROM.get(EEPROM_ADDR + sizeof(float) * i, vals[i]);
    if (isnan(vals[i])) {
      if (i == 0 || i == 1) vals[i] = dht.readTemperature();
      else vals[i] = dht.readHumidity();
    }
  }
}

void checkChanges() {
  if (temperature < vals[0]) {
    vals[0] = temperature;
    EEPROM.put(EEPROM_ADDR, vals[0]);
  }
  if (temperature > vals[1]) {
    vals[1] = temperature;
    EEPROM.put(EEPROM_ADDR + sizeof(float) * 1, vals[1]);
  }
  if (humidity < vals[2]) {
    vals[2] = humidity;
    EEPROM.put(EEPROM_ADDR + sizeof(float) * 2, vals[2]);
  }
  if (humidity > vals[3]) {
    vals[3] = humidity;
    EEPROM.put(EEPROM_ADDR + sizeof(float) * 3, vals[3]);
  }
}

void printScreen() {
  lcd.clear();
  lcd.setCursor(0,0);
  if (record == 1) lcd.print("\x01");
  if (record == 2) lcd.print("\x02");
  lcd.print("Temp.: " + String(temperature, 1) + "\x08" + "C");
  lcd.setCursor(0,1);
  if (record == 1) lcd.print("\x01");
  if (record == 2) lcd.print("\x02");
  lcd.print("Umid.: " + String(humidity, 1) + " %");
}