#include <ESP32Servo.h>
#include <Arduino.h>
#include <DHT.h>
#include <LiquidCrystal_I2C_Hangul.h>
#include <Wire.h>
#include <Stepper.h>
#include <WiFi.h>
#include <WiFiClient.h>

Servo servo;

#define DHT_PIN 2         
#define DHT_TYPE DHT22    

#define LDR_PIN 34        

#define RELAY_PIN 26 

#define LCD_ADDRESS 0x27
#define LCD_COLS 16
#define LCD_ROWS 2

#define LED_Red 19
#define LED_Green 15

const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 13, 12, 14, 5);

const int buttonPin = 4;
const float GAMMA = 0.7;
const float RL10 = 50;

DHT dht(DHT_PIN, DHT_TYPE);
LiquidCrystal_I2C_Hangul lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);

int pumpPin = 18; 
int angleOpen = 90; 
int angleClose = 0; 

int value = 1;
int previousValue = 0;
boolean buttonWasPressed = false;

void setup() { 
  Serial.begin(115200);
  myStepper.setSpeed(60);
  dht.begin();
  pinMode(LDR_PIN, INPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(LED_Red, OUTPUT);
  pinMode(LED_Green, OUTPUT);
  servo.attach(26);
  
  lcd.init(); 
  lcd.backlight();
  
  lcd.clear();
}

void loop() {
  
  int buttonState = digitalRead(buttonPin);

  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  // int lightIntensity = analogRead(LDR_PIN);
  // float lightPercent = map(lightIntensity, 4063, 32, 0, 100);
  int analogValue = analogRead(LDR_PIN); // Change A0 to the appropriate analog pin for ESP32
  float voltage = analogValue / 4095. * 3.3; // ESP32 has 12-bit ADC (4095 levels) and operates at 3.3V
  float resistance = 2000 * voltage / (1 - voltage / 3.3);
  float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA))/1.8;

  if(humidity < 80 || humidity >= 93 || temperature > 33 || temperature < 20 || lux > 1500 || lux < 500) {
    digitalWrite(LED_Red, HIGH);
    digitalWrite(LED_Green, LOW);
  } else {
    digitalWrite(LED_Green, HIGH);
    digitalWrite(LED_Red, LOW);
  }

  // mushroom need humidity between 80 and 95%
  if (humidity < 80) { 
    servo.write(angleOpen); 
    digitalWrite(pumpPin, HIGH); 
  } else if(humidity >= 93) {
    servo.write(angleClose); 
    digitalWrite(pumpPin, LOW); 
  }
  if(temperature > 33) {
    myStepper.step(120);
  } else {
    myStepper.step(0);
  }

    if (buttonState == HIGH && !buttonWasPressed) {
    delay(20);  // Debounce delay
    if (buttonState == HIGH) {  // Make sure the button is still pressed after debounce
      value++;
      buttonWasPressed = true;
      Serial.println("Button pressed! ");
    }
  } else if (buttonState == LOW) {
    buttonWasPressed = false;
  }
  delay(10);

  if (value != previousValue) {
    lcd.clear();
    if (value == 1) {
      lcd.setCursor(0, 0);
      lcd.print("Temp: ");
      lcd.print(temperature);
      lcd.print(" C");
 
      // mushroom need temperature around 20 - 33% celcius
      lcd.setCursor(0, 1);
      if(temperature > 33) {
        lcd.print("Too Hot ");
      } else if(temperature < 20) {
        lcd.print("Too Cold ");
      } else {
        lcd.print("well ");
      }
    } else if (value == 2) {
      lcd.setCursor(0, 0);
      lcd.print("Humidity: ");
      lcd.print(humidity);
      lcd.print(" %");

      // mushroom need humidity 80 - 95%
      lcd.setCursor(0, 1);
      if(humidity > 95) {
        lcd.print("Too Humid ");
      } else if(humidity < 80) {
        lcd.print("Too dry ");
      } else {
        lcd.print("well ");
      }
    } else if (value == 3) {
      lcd.setCursor(0, 0);
      lcd.print("Lux: ");
      lcd.print(lux);
      lcd.print("          ");

      lcd.setCursor(0, 1);
      if (lux > 1500) {
        lcd.print("too light");
      } else if(lux < 500) {
        lcd.print("too Dark");
      } else {
        lcd.print("well ");
      }
    }
    previousValue = value;
  }
  if(value > 3) {
    value = 1;
  }
}