#define BLYNK_TEMPLATE_ID "TMPL3_9SmenLl"
#define BLYNK_TEMPLATE_NAME "Smart Traffic Diversion Systems"
#define BLYNK_AUTH_TOKEN "PhashMcXKWbkuhbMlc4zBPEC2epjgDke"

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

const int redLedPin = 25;
const int yellowLedPin = 26;
const int greenLedPin = 27;
const int motionSensorPin = 32;

LiquidCrystal_I2C lcd(0x27, 16, 2);

char auth[] = "PhashMcXKWbkuhbMlc4zBPEC2epjgDke";
char ssid[] = "Wokwi-GUEST"; 
char pass[] = "";

enum TrafficLightState {
  RED,
    YELLOW,
      GREEN
      };

      TrafficLightState currentState = RED;
      unsigned long lastChangeTime = 0;
      const unsigned long interval = 3000;

      void setup() {
        Serial.begin(115200);
          Blynk.begin(auth, ssid, pass);
            lcd.init();
              lcd.backlight();
                pinMode(redLedPin, OUTPUT);
                  pinMode(yellowLedPin, OUTPUT);
                    pinMode(greenLedPin, OUTPUT);
                      pinMode(motionSensorPin, INPUT);
                        currentState = RED;
                          lastChangeTime = millis();
                          }

                          void loop() {
                            Blynk.run();
                              delay(10);

                                bool motionDetected = digitalRead(motionSensorPin) == HIGH;

                                  if (motionDetected) {
                                      currentState = RED;
                                          lastChangeTime = millis();
                                            } else {
                                                unsigned long currentTime = millis();
                                                    if (currentState == RED && currentTime - lastChangeTime >= interval) {
                                                          currentState = GREEN;
                                                                lastChangeTime = currentTime;
                                                                    } else if (currentState == GREEN && currentTime - lastChangeTime >= interval) {
                                                                          currentState = YELLOW;
                                                                                lastChangeTime = currentTime;
                                                                                    } else if (currentState == YELLOW && currentTime - lastChangeTime >= interval / 2) {
                                                                                          currentState = RED;
                                                                                                lastChangeTime = currentTime;
                                                                                                    }
                                                                                                      }

                                                                                                        digitalWrite(redLedPin, currentState == RED ? HIGH : LOW);
                                                                                                          digitalWrite(yellowLedPin, currentState == YELLOW ? HIGH : LOW);
                                                                                                            digitalWrite(greenLedPin, currentState == GREEN ? HIGH : LOW);

                                                                                                              Blynk.virtualWrite(V1, currentState == RED ? 255 : 0);
                                                                                                                Blynk.virtualWrite(V2, currentState == YELLOW ? 255 : 0);
                                                                                                                  Blynk.virtualWrite(V3, currentState == GREEN ? 255 : 0);

                                                                                                                    if (motionDetected) {
                                                                                                                        Blynk.virtualWrite(V4, "Ambulance! Wait!");
                                                                                                                            lcd.clear();
                                                                                                                                lcd.setCursor(0, 0);
                                                                                                                                    lcd.print("Red");
                                                                                                                                        lcd.setCursor(0, 1);
                                                                                                                                            lcd.print("Ambulance! Wait!");
                                                                                                                                              } else {
                                                                                                                                                  Blynk.virtualWrite(V4, "Normal Traffic");
                                                                                                                                                      lcd.clear();
                                                                                                                                                          lcd.setCursor(0, 0);
                                                                                                                                                              switch (currentState) {
                                                                                                                                                                    case RED:
                                                                                                                                                                            lcd.print("Red");
                                                                                                                                                                                    lcd.setCursor(0, 1);
                                                                                                                                                                                            lcd.print("Normal Traffic");
                                                                                                                                                                                                    break;
                                                                                                                                                                                                          case GREEN:
                                                                                                                                                                                                                  lcd.print("Green");
                                                                                                                                                                                                                          lcd.setCursor(0, 1);
                                                                                                                                                                                                                                  lcd.print("Normal Traffic");
                                                                                                                                                                                                                                          break;
                                                                                                                                                                                                                                                case YELLOW:
                                                                                                                                                                                                                                                        lcd.print("Yellow");
                                                                                                                                                                                                                                                                lcd.setCursor(0, 1);
                                                                                                                                                                                                                                                                        lcd.print("Normal Traffic");
                                                                                                                                                                                                                                                                                break;
                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                          delay(1000);
                                                                                                                                                                                                                                                                                          }