#include "DHTesp.h"
#include <Wire.h>
#include <Adafruit_SSD1306.h>

// create GPIO variables
#define soilMoisture_pin  4
#define photoResistor_pin 26
#define dht_pin           32 
#define led_pin           33
#define us_to_s           1000000ULL
#define SLEEP_TIME        5

// define oled settings
#define SCREEN_WIDTH      128
#define SCREEN_HEIGHT     64
#define SCREEN_ADDRESS    0x3C
#define OLED_RESET        4

RTC_DATA_ATTR int bootCount = 0;

// create I/O device object
DHTesp dht;
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// declaring variables
bool goldilockHumidity = true;
bool goldilockTemperature = true;
bool goldilockSunlight = true;
String sunLight;

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup() {
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  delay(1000);

  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  print_wakeup_reason();

  esp_sleep_enable_timer_wakeup(SLEEP_TIME * us_to_s);
  Serial.println("Setup ESP32 to sleep for every " + String(SLEEP_TIME) + " Seconds");
  
  pinMode(led_pin, OUTPUT);
  dht.setup(dht_pin, DHTesp::DHT22);


}

void loop() {
  delay(2000);
  
  TempAndHumidity  data = dht.getTempAndHumidity();
  // read relative humidity from DHT11 sensor
  //int humidity = dht.readHumidity();
  int humidity = data.humidity;
  // read temperature (degress Fahrenheit) from DHT11 sensor
  //float temperature = dht.readTemperature(true);
  float temperature = data.temperature;

  // check if any reads failed; try to read again.
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }
  
  // read the ADC value on light sensor (ADC2_CH9).
  int photoResistorValue = analogRead(photoResistor_pin);

  // read sun light brightness from ADC value
  if (photoResistorValue <= 4095 && photoResistorValue > 3000) {
    sunLight = "bright";
  }
  if (photoResistorValue < 3000 && photoResistorValue > 2000) {
    sunLight = "dim";
  }
  if (photoResistorValue < 2000) {
    sunLight = "dark";
  }
  
  //LED Warning
  if (humidity > 40.0 || humidity < 40.0) {
    goldilockHumidity = false;
  }
  else {
    goldilockHumidity = true;
  }

  if (temperature > 75.0 || temperature < 65.0) {
    goldilockTemperature = false;
  }
  else {
    goldilockTemperature = true;
  }
  
  if (sunLight != "bright") {
    goldilockSunlight = false;
  }
  else {
    goldilockSunlight = true;
  }

  String plantMood;
  if (goldilockHumidity && goldilockTemperature && goldilockSunlight) {
    digitalWrite(led_pin, LOW);
    plantMood = "Happy";
  }
  else {
    digitalWrite(led_pin, HIGH);
    plantMood = "Sad";
  }
  
  // plot data to Serial plotter.
  Serial.print("Temperature(°F):");
  Serial.println(temperature);
  Serial.println(goldilockTemperature);

  Serial.print("Humidity(%):");
  Serial.println(humidity);
  Serial.println(goldilockHumidity);

  Serial.print("Light_Brightness:");
  Serial.println(photoResistorValue);
  Serial.println(goldilockSunlight);

  Serial.println("Over all plant mood: " + plantMood);
  Serial.println("---------------------------------");

  delay(5000);
  Serial.println("Going to sleep now");
  Serial.flush();
  esp_deep_sleep_start();
}