// btn 18 5 17 16 left to right
#include "WiFi.h"     //เรียกใช้งานไลบรารี่ wifi
#include <WiFiUDP.h>  //เรียกใช้งานไลบรารี่ UDP
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const char *ssid = "Freewifi";       //ชื่อ wifi ที่ต้องการเชื่อมต่อ
const char *password = "123456789";  //password ที่ต้องการเชื่อมต่อ
unsigned int UDPPort = 2390;         // เปิดใช้งานพอร์ต 2390

int packetSize;

String BufferString;
int len;
String data;
WiFiUDP Udp;                              //เปิดใช้ฟังชั่น UDP
IPAddress local_ip = { 192, 168, 1, 2 };  //ตั้งค่า IP
IPAddress gateway = { 192, 168, 1, 1 };   //ตั้งค่า IP Gateway
IPAddress subnet = { 255, 255, 255, 0 };  //ตั้งค่า Subnet
void automode();
void automode();
void twotown();
void smalltown();
void bigtown();
int wallmode = 0;
int kj = 0;
int rain = 0;
int i = 1;   //loop pointer
int j = 1;   //loop pointer14
int k1 = 0;  //loop pointer
int k2 = 0;
int k3 = 0;
int k4 = 0;
int point = 0;  //pointer at home screen
int screen = 0;


LiquidCrystal_I2C lcd(0x27, 20, 4);  //address lcd
int relaylist[] = { 23, 19, 4, 2, 15, 32, 33, 25, 26, 27 };
int buzzer = 12;
void setup() {
  Serial.begin(115200);
  Serial.print("Connecting to ");          //แสดงข้อความ "Connecting to"
  Serial.println(ssid);                    //แสดงข้อความ ชื่อ wifi
  WiFi.begin(ssid, password);              // เชื่อมต่อ wifi
  while (WiFi.status() != WL_CONNECTED) {  //รอจนกว่าจะเชื่อมต่อสําเร็จ
    delay(500);
    Serial.print(".");
  }
  Serial.print("WiFi UDP Mode : ");

  WiFi.config(local_ip, gateway, subnet);  //set ค่า IP
  Serial.println(WiFi.localIP());          //แสดงหมายเลข IP ของ ESP32
  Udp.begin(UDPPort);                      //เริ่มใช้งานฟังชั่น UDP

  Serial.println("");
  Serial.println("WiFi connected");  //แสดงข้อความเชื่อมต่อสําเร็จ
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.begin(115200);

  for (int a = 0; a < sizeof(relaylist); a++) {  //loop for pinmode relay
    pinMode(relaylist[a], OUTPUT);
  }
  for (int a = 0; a < sizeof(relaylist); a++) {
    digitalWrite(relaylist[a], 1);
  }
  pinMode(34, INPUT);
  pinMode(14, OUTPUT);
  pinMode(16, INPUT_PULLUP);  //red btn
  pinMode(17, INPUT_PULLUP);  //green btn
  pinMode(5, INPUT_PULLUP);   //blue btn
  pinMode(18, INPUT_PULLUP);  //yellow btn
  pinMode(buzzer, OUTPUT);    // เสียงกดปุ่ม
  lcd.begin();
  lcd.backlight();
  digitalWrite(14, 1);
  lcd.setCursor(0, 0);
  lcd.print("********************");
  lcd.setCursor(0, 1);  // ไปที่ตัวอักษรที่ 0 แถวที่ 1
  lcd.print("*Welcome To        *");
  lcd.setCursor(0, 2);  // ไปที่ตัวอักษรที่ 7 แถวที่ 2
  lcd.print("*        ELYSIUM!! *");
  lcd.setCursor(0, 3);
  lcd.print("*********************");
  delay(2000);
  lcd.clear();
}

void loop() {
  if (digitalRead(5) == 0) {
    lcd.clear();
    i = 1;
    screen = 0;
    //loop pointer
    j = 1;   //loop pointer14
    k1 = 0;  //loop pointer
    k2 = 0;
    k3 = 0;
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    k4 = 0;
  }


  if (i == 1 and screen == 0) {
    lcd.setCursor(2, 0);
    lcd.print("SELECT CITY MODE");
    lcd.setCursor(3, 1);
    lcd.print("SELECTED AUTO  ");
    lcd.setCursor(0, 2);
    lcd.print("MODE : >AUTO<  ");
    lcd.setCursor(7, 3);
    lcd.print(" MANUAL ");
    point = 1;
    wallmode = 1;
    for (int a = 0; a < sizeof(relaylist); a++) {
      digitalWrite(relaylist[a], 1);
    }
    digitalWrite(14, 1);
  }

  if (i == 2 and screen == 0) {
    lcd.setCursor(2, 0);
    lcd.print("SELECT CITY MODE");
    lcd.setCursor(3, 1);
    lcd.print("SELECTED MANUAL");
    lcd.setCursor(0, 2);
    lcd.print("MODE :  AUTO ");
    lcd.setCursor(7, 3);
    lcd.print(">MANUAL<");
    point = 2;
    wallmode = 1;
    for (int a = 0; a < sizeof(relaylist); a++) {
      digitalWrite(relaylist[a], 1);
    }
    digitalWrite(14, 1);
  }

  if (digitalRead(18) == 0 and screen == 0) {  //pointer เลื่อนได้
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    i = i + 1;
    delay(250);
  }

  if (i > 2) {  //pointer วน
    i = 1;
  }

  if (digitalRead(17) == 0 and screen == 0) {
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    screen = 1;
    i = 0;
    delay(250);
    lcd.clear();
  }

  if (screen == 1 and point == 1) {
    int daylight = analogRead(34);
    digitalWrite(14, 0);
    if (daylight < 2000) {

      automodeoff();
      lcd.setCursor(5, 0);
      lcd.print("'AUTO MODE'");
      lcd.setCursor(6, 1);
      lcd.print("   DAY   ");
      lcd.setCursor(7, 2);
      lcd.print("RUNNING");
      delay(250);
    } else {
      automode();
      lcd.setCursor(5, 0);
      lcd.print("'AUTO MODE'");
      lcd.setCursor(8, 1);
      lcd.print("NIGHT");
      lcd.setCursor(7, 2);
      lcd.print("RUNNING");
      delay(250);
    }
    wallmode = 1;
  }

  if (digitalRead(16) == 0) {
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    screen = screen - 1;
    delay(250);
    i = 1;

    lcd.clear();
  }
  if (screen < 0) {
    screen = 0;
  }
  if (screen > 3) {
    screen = 3;
  }

  if (screen == 1 and point == 2 and j == 1) {
    lcd.setCursor(0, 0);
    lcd.print(">SMALLTOWN");
    lcd.setCursor(0, 1);
    lcd.print(" TWOTOWN");
    lcd.setCursor(0, 2);
    lcd.print(" BIGTOWN");
    lcd.setCursor(0, 3);
    lcd.print(" SENSOR");
    wallmode = 2;
  }

  if (screen == 1 and point == 2 and j == 2) {
    lcd.setCursor(0, 0);
    lcd.print(" SMALLTOWN");
    lcd.setCursor(0, 1);
    lcd.print(">TWOTOWN");
    lcd.setCursor(0, 2);
    lcd.print(" BIGTOWN");
    lcd.setCursor(0, 3);
    lcd.print(" SENSOR");
    wallmode = 2;
  }

  if (screen == 1 and point == 2 and j == 3) {
    lcd.setCursor(0, 0);
    lcd.print(" SMALLTOWN");
    lcd.setCursor(0, 1);
    lcd.print(" TWOTOWN");
    lcd.setCursor(0, 2);
    lcd.print(">BIGTOWN");
    lcd.setCursor(0, 3);
    lcd.print(" SENSOR");
    wallmode = 2;
  }
  if (screen == 1 and point == 2 and j == 4) {
    lcd.setCursor(0, 0);
    lcd.print(" SMALLTOWN");
    lcd.setCursor(0, 1);
    lcd.print(" TWOTOWN");
    lcd.setCursor(0, 2);
    lcd.print(" BIGTOWN");
    lcd.setCursor(0, 3);
    lcd.print(">SENSOR");
    wallmode = 2;
  }

  if (digitalRead(18) == 0 and screen == 1) {  //pointer เลื่อนได้
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    j = j + 1;
    delay(250);
  }

  if (j > 4) {
    j = 1;
  }
  if (digitalRead(17) == 0 and screen == 1 and wallmode == 2) {
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    screen = 2;
    delay(250);
    lcd.clear();
  }
  if (screen == 2 and j == 1) {
    if (k1 == 0) {
      lcd.setCursor(0, 0);
      lcd.print(">TURN ON THE LIGHT");
      lcd.setCursor(0, 1);
      lcd.print(" TURN OFF THE LIGHT");
    }
    if (digitalRead(18) == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      k1 = k1 + 1;
      delay(250);
    }
    if (k1 == 1) {
      lcd.setCursor(0, 0);
      lcd.print(" TURN ON THE LIGHT");
      lcd.setCursor(0, 1);
      lcd.print(">TURN OFF THE LIGHT");
    }
    if (k1 > 1) {
      k1 = 0;
    }
    if (digitalRead(17) == 0 and k1 == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      smalltown();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" LIGHT SMALLTOWN ON ");
      delay(1500);
      lcd.clear();
    }
    if (digitalRead(17) == 0 and k1 == 1) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      smalltownoff();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("LIGHT SMALLTOWN OFF");
      delay(1500);
      lcd.clear();
    }
  }
  if (screen == 2 and j == 2) {
    if (k2 == 0) {
      lcd.setCursor(0, 0);
      lcd.print(">ON Light");
      lcd.setCursor(0, 1);
      lcd.print(" OFF Light");
    }
    if (digitalRead(18) == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      k2 = k2 + 1;
      delay(250);
    }
    if (k2 == 1) {
      lcd.setCursor(0, 0);
      lcd.print(" ON Light");
      lcd.setCursor(0, 1);
      lcd.print(">OFF Light");
    }
    if (k2 > 1) {
      k2 = 0;
    }
    if (digitalRead(17) == 0 and k2 == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      twotown();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("LIGHT TWOTOWN ON ");
      delay(1500);
      lcd.clear();
    }
    if (digitalRead(17) == 0 and k2 == 1) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      twotownoff();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("LIGHT TWOTOWN OFF");
      delay(1500);
      lcd.clear();
    }
  }
  if (screen == 2 and j == 3) {
    if (k3 == 0) {
      lcd.setCursor(0, 0);
      lcd.print(">ON Light");
      lcd.setCursor(0, 1);
      lcd.print(" OFF Light");
    }
    if (digitalRead(18) == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      k3 = k3 + 1;
      delay(250);
    }
    if (k3 == 1) {
      lcd.setCursor(0, 0);
      lcd.print(" ON Light");
      lcd.setCursor(0, 1);
      lcd.print(">OFF Light");
    }
    if (k3 > 1) {
      k3 = 0;
    }
    if (digitalRead(17) == 0 and k3 == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      bigtown();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("LIGHT BIGTOWN ON ");
      delay(1500);
      lcd.clear();
    }
    if (digitalRead(17) == 0 and k3 == 1) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      bigtownoff();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" LIGHT BIGTOWN OFF");
      delay(1500);
      lcd.clear();
    }
  }
  if (screen == 2 and j == 4) {
    if (k4 == 0 and screen == 2) {
      lcd.setCursor(0, 0);
      lcd.print(">MQ ");
      lcd.setCursor(0, 1);
      lcd.print(" ULTRASONIC ");
      lcd.setCursor(0, 2);
      lcd.print(" RAIN SENSOR ");
    }
    if (k4 == 1 and screen == 2) {
      lcd.setCursor(0, 0);
      lcd.print(" MQ ");
      lcd.setCursor(0, 1);
      lcd.print(">ULTRASONIC ");
      lcd.setCursor(0, 2);
      lcd.print(" RAIN SENSOR ");
    }
    if (k4 == 2 and screen == 2) {
      lcd.setCursor(0, 0);
      lcd.print(" MQ ");
      lcd.setCursor(0, 1);
      lcd.print(" ULTRASONIC ");
      lcd.setCursor(0, 2);
      lcd.print(">RAIN SENSOR ");
    }
    if (digitalRead(18) == 0) {
      digitalWrite(buzzer, 1);
      delay(50);
      digitalWrite(buzzer, 0);
      k4 = k4 + 1;
      delay(250);
    }
  }
  if (k4 > 2) {
    k4 = 0;
  }

  if (digitalRead(17) == 0 and k4 == 0) {
    screen = 3;
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    lcd.clear();
  }
  if (digitalRead(17) == 0 and k4 == 1) {
    screen = 3;
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    lcd.clear();
  }
  if (digitalRead(17) == 0 and k4 == 2) {
    screen = 3;
    digitalWrite(buzzer, 1);
    delay(50);
    digitalWrite(buzzer, 0);
    lcd.clear();
  }
  if (screen == 3 and k4 == 0) {
    kj = 2;
  }
  if (kj == 2) {
    for (;;) {
      packetSize = Udp.parsePacket();  // Check for incoming packets
      if (packetSize) {
        char packetBuffer[packetSize + 1];
        len = Udp.read(packetBuffer, packetSize);
        packetBuffer[len] = '\0';
        // Extract data from the received packet
        String receivedData = String(packetBuffer);
        // Find the position of the comma
        int firstCommaIndex = receivedData.indexOf(',');
        int secondCommaIndex = receivedData.indexOf(',', firstCommaIndex + 1);
        int thirdCommaIndex = receivedData.indexOf(',', secondCommaIndex + 1);
        // Split the received data into two parts based on the position of "Sensor2,"

        if (firstCommaIndex != -1 && secondCommaIndex != -1) {
          // Extract data for Sensor1
          String data1 = receivedData.substring(0, firstCommaIndex);
          // Extract data for Sensor2
          String data2 = receivedData.substring(firstCommaIndex + 1, secondCommaIndex);
          // Extract data for Sensor3
          String data3 = receivedData.substring(secondCommaIndex + 1, thirdCommaIndex);
          // Display the data on the LCD
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("MQ1: " + data2);
          lcd.setCursor(0, 1);
          lcd.print("MQ2: " + data3);
        } else {
          Serial.println("Invalid received data format");
        }
      }

      if (digitalRead(16) == 0) {
        digitalWrite(buzzer, 1);
        delay(50);
        digitalWrite(buzzer, 0);
        screen = screen - 1;
        delay(250);
        i = 1;
        kj = 0;
        lcd.clear();
        break;
      }
      delay(500);
      lcd.setCursor(8, 0);
      lcd.print("       ");
      lcd.setCursor(8, 1);
      lcd.print("       ");
      data = "";
    }
  }
  if (screen == 3 and k4 == 1) {
    kj = 1;
  }
  if (kj == 1) {
    for (;;) {
      packetSize = Udp.parsePacket();  // Check for incoming packets
      if (packetSize) {
        char packetBuffer[packetSize + 1];
        len = Udp.read(packetBuffer, packetSize);
        packetBuffer[len] = '\0';
        // Extract data from the received packet
        String receivedData = String(packetBuffer);
        // Find the position of the comma
        int commaIndex = receivedData.indexOf(',');
        // Split the received data into two parts based on the position of "Sensor2,"

        if (commaIndex != -1) {
          // Extract data for Sensor1
          String data1 = receivedData.substring(0, commaIndex);
          // Extract data for Sensor2
          String data2 = receivedData.substring(commaIndex + 1);
          // Display the data on the LCD
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Distance : " + data1 + " cm");
          //lcd.setCursor(0, 1);
          //lcd.print("Sensor2: " + data2);
        } else {
          Serial.println("Invalid received data format");
        }
      }

      if (digitalRead(16) == 0) {
        digitalWrite(buzzer, 1);
        delay(50);
        digitalWrite(buzzer, 0);
        screen = screen - 1;
        delay(250);
        i = 1;
        kj = 0;
        lcd.clear();
        break;
      }
      delay(500);
      lcd.setCursor(8, 0);
      lcd.print("       ");
      lcd.setCursor(8, 1);
      lcd.print("       ");
      data = "";
    }
  }
  if (screen == 3 and k4 == 2) {
    kj = 2;
  }
  if (kj == 2) {
    for (;;) {
      packetSize = Udp.parsePacket();  // Check for incoming packets
      if (packetSize) {
        char packetBuffer[packetSize + 1];
        len = Udp.read(packetBuffer, packetSize);
        packetBuffer[len] = '\0';
        // Extract data from the received packet
        String receivedData = String(packetBuffer);
        // Find the position of the comma
        int firstCommaIndex = receivedData.indexOf(',');
        int secondCommaIndex = receivedData.indexOf(',', firstCommaIndex + 1);
        int thirdCommaIndex = receivedData.indexOf(',', secondCommaIndex + 1);

        // Split the received data into two parts based on the position of "Sensor2,"

        if (firstCommaIndex != -1) {
          String data1 = receivedData.substring(0, firstCommaIndex);
          // Extract data for Sensor2
          String data2 = receivedData.substring(firstCommaIndex + 1, secondCommaIndex);
          // Extract data for Sensor3
          String data3 = receivedData.substring(secondCommaIndex + 1, thirdCommaIndex);
          // Extract data for Sensor4
          String data4 = receivedData.substring(thirdCommaIndex + 1);
          int rain = data4.toInt();
          if (rain == 0) {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("It's rainy");
          } else if (rain == 1) {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("No rain ");
          } else {
            Serial.println("Invalid received data format");
          }
        }

        if (digitalRead(16) == 0) {
          digitalWrite(buzzer, 1);
          delay(50);
          digitalWrite(buzzer, 0);
          screen = screen - 1;
          delay(250);
          i = 1;
          kj = 0;
          lcd.clear();
          break;
        }
        delay(500);
        lcd.setCursor(8, 0);
        lcd.print("       ");
        lcd.setCursor(8, 1);
        lcd.print("       ");
        data = "";
      }
    }
  }
}



void automode() {

  for (int a = 0; a < sizeof(relaylist); a++) {
    digitalWrite(relaylist[a], 0);
  }
}
void automodeoff() {
  for (int a = 0; a < sizeof(relaylist); a++) {
    digitalWrite(relaylist[a], 1);
  }
}
void twotown() {

  digitalWrite(23, 0);
  digitalWrite(19, 0);
  digitalWrite(4, 0);
  //digitalWrite(13,0);
}
void twotownoff() {

  digitalWrite(23, 1);
  digitalWrite(19, 1);
  digitalWrite(4, 1);
  //digitalWrite(13,1);
}
void smalltown() {
  digitalWrite(2, 0);
  digitalWrite(15, 0);
}
void smalltownoff() {
  digitalWrite(2, 1);
  digitalWrite(15, 1);
}
void bigtown() {
  digitalWrite(32, 0);
  digitalWrite(33, 0);
  digitalWrite(25, 0);
  digitalWrite(26, 0);
}
void bigtownoff() {
  digitalWrite(32, 1);
  digitalWrite(33, 1);
  digitalWrite(25, 1);
  digitalWrite(26, 1);
}