#include <OneWire.h>
#include <DallasTemperature.h>
#include "DHT.h"
#include <LiquidCrystal_I2C.h>

#define PIN_DHT 2       // Pin para el sensor DHT
#define TIPO_DHT DHT22  // Tipo de sensor DHT

#define PIN_LED 12      // Pin para el LED
#define PIN_ALARMA 13   // Pin para la alarma sonora
#define PIN_DS18B20_1 10 // Pin para el sensor DS18B20 (temperatura piel 1)
#define PIN_DS18B20_2 9  // Pin para el sensor DS18B20 (temperatura piel 2)

#define I2C_ADDR    0x27
#define LCD_COLUMNS 16
#define LCD_LINES   2


LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);

DHT sensorDHT(PIN_DHT, TIPO_DHT);
OneWire oneWireDS18B20_1(PIN_DS18B20_1);
OneWire oneWireDS18B20_2(PIN_DS18B20_2);
DallasTemperature sensorTemperatura_1(&oneWireDS18B20_1);
DallasTemperature sensorTemperatura_2(&oneWireDS18B20_2);

// a Simple Button class
// brought the "debounce" example towards OOP


class Button {                         // a simple class for buttons based on the "Debounce" example
    const byte buttonPin;              // the GPIO / pin for the button
    static constexpr byte debounceDelay = 30;    // the debounce time; increase if the output flickers. Static because we only need one value for all buttons
    const bool active;                 // is the pin active HIGH or active LOW (will also activate the pullups!)
    bool lastButtonState = HIGH;       // the previous reading from the input pin
    byte lastDebounceTime = 0;         // the last time the output pin was toggled - we check only ONE byte, so I didn't mess around with unsigned long

  public:
    /**
       \brief constructor for a button

       The constructor takes the GPIO as parameter.
       If you omit the second parameter, the library will activate the internal pullup resistor
       and the button should connect to GND.
       If you set the second parameter to HIGH, the button is active HIGH. 
       The button should connect to VCC. 
       The internal pullups will not be used but you will need an external pulldown resistor.

       \param attachTo the GPIO for the button
       \param active LOW (default) - if button connects to GND, HIGH if button connects to VCC
    */
    Button(byte attachTo, bool active = LOW) : buttonPin(attachTo), active(active) {}

    /**
       \brief set the pin to the proper state

       Call this function in your setup().
       The pinMode will be set according to your constructor.
    */
    void begin() {
      if (active == LOW)
        pinMode(buttonPin, INPUT_PULLUP);
      else
        pinMode(buttonPin, INPUT);
    }

    /**
        \brief indicate if button was pressed since last call

        @return HIGH if button was pressed since last call - debounce
    */
    bool wasPressed() {
      bool buttonState = LOW;                                        // the current reading from the input pin
      byte reading = LOW;                                            // "translated" state of button LOW = released, HIGH = pressed, despite the electrical state of the input pint
      if (digitalRead(buttonPin) == active) reading = HIGH;          // if we are using INPUT_PULLUP we are checking invers to LOW Pin
      if (((millis() & 0xFF ) - lastDebounceTime) > debounceDelay)   // If the switch changed, AFTER any pressing or noise
      {
        if (reading != lastButtonState && lastButtonState == LOW)    // If there was a change and and last state was LOW (= released)
        {
          buttonState = HIGH;
        }
        lastDebounceTime = millis() & 0xFF;
        lastButtonState = reading;
      }
      return buttonState;
    }
};

Button buttonA{A0};
Button buttonB{A1};
Button buttonC{A2};


void setup() {
  Serial.begin(115200);
  delay(2);

    buttonA.begin();
  buttonB.begin();
  buttonC.begin();

  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_ALARMA, OUTPUT);
  digitalWrite(PIN_LED, LOW);    // Asegúrate de que el LED esté apagado al inicio
  digitalWrite(PIN_ALARMA, LOW); // Asegúrate de que la alarma esté apagada al inicio


  sensorTemperatura_1.begin();
  sensorTemperatura_2.begin();
  sensorDHT.begin();

  // Inicialización de la pantalla LCD
  lcd.init();
  lcd.backlight();
  lcd.clear();  // Limpiar la pantalla
 
}

void loop() {
  lcd.setCursor(0,0);
   lcd.print("Seleccione MODO:");
   lcd.setCursor(0,1);
   lcd.print("A)    B)    C)");
  delay(1000);

   if (buttonA.wasPressed()) {do{

     lcd.clear();

    sensorTemperatura_1.requestTemperatures();
  sensorTemperatura_2.requestTemperatures();

  float temperaturaPiel_1 = sensorTemperatura_1.getTempCByIndex(0);
  float temperaturaPiel_2 = sensorTemperatura_2.getTempCByIndex(0);
  float temperaturaAmbiente = sensorDHT.readTemperature();
  float humedad = sensorDHT.readHumidity();

  // Limpia la pantalla
  lcd.clear();
  
  // Muestra las lecturas en la pantalla
  lcd.setCursor(0, 0);
  lcd.print("Temp Amb: ");
  lcd.print(temperaturaAmbiente);
  lcd.print(" C");

  lcd.setCursor(0, 1);
  lcd.print("Temp P1: ");
  lcd.print(temperaturaPiel_1);
  lcd.print("*C");
  delay(2000);

    // Limpia la pantalla
  lcd.clear();
  
  // Muestra las lecturas en la pantalla
  lcd.setCursor(0, 0);
  lcd.print("Humedad: ");
  lcd.print(humedad);
  lcd.print(" %");

  lcd.setCursor(0, 1);
  lcd.print("Temp P2: ");
  lcd.print(temperaturaPiel_2);
  lcd.print("*C");
  delay(2000);

    // Limpia la pantalla
  lcd.clear();



  // Condiciones para encender el LED y la alarma sonora
  if ((temperaturaAmbiente < 27 || temperaturaAmbiente > 34) ||
      (temperaturaPiel_1 < 34 || temperaturaPiel_1 > 35) ||
      (temperaturaPiel_2 < 34 || temperaturaPiel_2 > 35) ||
      (humedad < 20 || humedad > 60)) {
    lcd.setCursor(0, 0);
    lcd.print("Advertencia!");
    
    // Identifica cuál variable está fuera de rango
    if (temperaturaAmbiente < 27 || temperaturaAmbiente > 34)
    lcd.setCursor(0, 1);
      lcd.print("Amb");

    if (temperaturaPiel_1 < 34 || temperaturaPiel_1 > 35)
    lcd.setCursor(4, 1);
      lcd.println("TP1");

    if (temperaturaPiel_2 < 34 || temperaturaPiel_2 > 35)
    lcd.setCursor(8, 1);
      lcd.println("TP2");

    if (humedad < 20 || humedad > 60)
    lcd.setCursor(10, 1);
      lcd.println("Hu");

    digitalWrite(PIN_LED, HIGH);   // Enciende el LED
    digitalWrite(PIN_ALARMA, HIGH); // Enciende la alarma sonora
  } else {
    digitalWrite(PIN_LED, LOW);    // Apaga el LED
    digitalWrite(PIN_ALARMA, LOW);  // Apaga la alarma sonora
  }

  // Espera antes de la siguiente lectura
  delay(5000); // Espera 5 segundos entre cada medición

   }while(1);}

   if (buttonB.wasPressed()) {do{

     lcd.clear();

    sensorTemperatura_1.requestTemperatures();
  sensorTemperatura_2.requestTemperatures();

  float temperaturaPiel_1 = sensorTemperatura_1.getTempCByIndex(0);
  float temperaturaPiel_2 = sensorTemperatura_2.getTempCByIndex(0);
  float temperaturaAmbiente = sensorDHT.readTemperature();
  float humedad = sensorDHT.readHumidity();

  // Limpia la pantalla
  lcd.clear();
  
  // Muestra las lecturas en la pantalla
  lcd.setCursor(0, 0);
  lcd.print("Temp Amb: ");
  lcd.print(temperaturaAmbiente);
  lcd.print(" C");

  lcd.setCursor(0, 1);
  lcd.print("Temp P1: ");
  lcd.print(temperaturaPiel_1);
  lcd.print("*C");
  delay(2000);

    // Limpia la pantalla
  lcd.clear();
  
  // Muestra las lecturas en la pantalla
  lcd.setCursor(0, 0);
  lcd.print("Humedad: ");
  lcd.print(humedad);
  lcd.print(" %");

  lcd.setCursor(0, 1);
  lcd.print("Temp P2: ");
  lcd.print(temperaturaPiel_2);
  lcd.print("*C");
  delay(2000);

    // Limpia la pantalla
  lcd.clear();



  // Condiciones para encender el LED y la alarma sonora
  if ((temperaturaAmbiente < 27 || temperaturaAmbiente > 34) ||
      (temperaturaPiel_1 < 35 || temperaturaPiel_1 > 36) ||
      (temperaturaPiel_2 < 35 || temperaturaPiel_2 > 36) ||
      (humedad < 20 || humedad > 60)) {
    lcd.setCursor(0, 0);
    lcd.print("Advertencia!");
    
    // Identifica cuál variable está fuera de rango
    if (temperaturaAmbiente < 27 || temperaturaAmbiente > 34)
    lcd.setCursor(0, 1);
      lcd.print("Amb");

    if (temperaturaPiel_1 < 35 || temperaturaPiel_1 > 36)
    lcd.setCursor(4, 1);
      lcd.println("TP1");

    if (temperaturaPiel_2 < 35 || temperaturaPiel_2 > 36)
    lcd.setCursor(8, 1);
      lcd.println("TP2");

    if (humedad < 20 || humedad > 60)
    lcd.setCursor(10, 1);
      lcd.println("Hu");

    digitalWrite(PIN_LED, HIGH);   // Enciende el LED
    digitalWrite(PIN_ALARMA, HIGH); // Enciende la alarma sonora
  } else {
    digitalWrite(PIN_LED, LOW);    // Apaga el LED
    digitalWrite(PIN_ALARMA, LOW);  // Apaga la alarma sonora
  }

  // Espera antes de la siguiente lectura
  delay(5000); // Espera 5 segundos entre cada medición

    
    }while(1);}

  if (buttonC.wasPressed()){ do{

     lcd.clear();

    sensorTemperatura_1.requestTemperatures();
  sensorTemperatura_2.requestTemperatures();

  float temperaturaPiel_1 = sensorTemperatura_1.getTempCByIndex(0);
  float temperaturaPiel_2 = sensorTemperatura_2.getTempCByIndex(0);
  float temperaturaAmbiente = sensorDHT.readTemperature();
  float humedad = sensorDHT.readHumidity();

  // Limpia la pantalla
  lcd.clear();
  
  // Muestra las lecturas en la pantalla
  lcd.setCursor(0, 0);
  lcd.print("Temp Amb: ");
  lcd.print(temperaturaAmbiente);
  lcd.print(" C");

  lcd.setCursor(0, 1);
  lcd.print("Temp P1: ");
  lcd.print(temperaturaPiel_1);
  lcd.print("*C");
  delay(2000);

    // Limpia la pantalla
  lcd.clear();
  
  // Muestra las lecturas en la pantalla
  lcd.setCursor(0, 0);
  lcd.print("Humedad: ");
  lcd.print(humedad);
  lcd.print(" %");

  lcd.setCursor(0, 1);
  lcd.print("Temp P2: ");
  lcd.print(temperaturaPiel_2);
  lcd.print("*C");
  delay(2000);

    // Limpia la pantalla
  lcd.clear();



  // Condiciones para encender el LED y la alarma sonora
  if ((temperaturaAmbiente < 27 || temperaturaAmbiente > 34) ||
      (temperaturaPiel_1 < 36 || temperaturaPiel_1 > 37) ||
      (temperaturaPiel_2 < 36 || temperaturaPiel_2 > 37) ||
      (humedad < 20 || humedad > 60)) {
    lcd.setCursor(0, 0);
    lcd.print("Advertencia!");
    
    // Identifica cuál variable está fuera de rango
    if (temperaturaAmbiente < 27 || temperaturaAmbiente > 34)
    lcd.setCursor(0, 1);
      lcd.print("Amb");

    if (temperaturaPiel_1 < 36 || temperaturaPiel_1 > 37)
    lcd.setCursor(4, 1);
      lcd.println("TP1");

    if (temperaturaPiel_2 < 36 || temperaturaPiel_2 > 37)
    lcd.setCursor(8, 1);
      lcd.println("TP2");

    if (humedad < 20 || humedad > 60)
    lcd.setCursor(10, 1);
      lcd.println("Hu");

    digitalWrite(PIN_LED, HIGH);   // Enciende el LED
    digitalWrite(PIN_ALARMA, HIGH); // Enciende la alarma sonora
  } else {
    digitalWrite(PIN_LED, LOW);    // Apaga el LED
    digitalWrite(PIN_ALARMA, LOW);  // Apaga la alarma sonora
  }

  // Espera antes de la siguiente lectura
  delay(5000); // Espera 5 segundos entre cada medición

 
  
}while(1);}

}