#include <WiFi.h>
#include <WebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

const char* ssid = "Tute";
const char* password = "877855524";

#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define BUZZER_PIN 25
WebServer server(80);
float temperatureC = 0;

struct TempRange {
  String name;
  float minTemp;
  float maxTemp;
};

TempRange items[] = {
  {"Human Body", 36.1, 37.2},
  {"Room", 20.0, 26.0},
  {"Drinking Water", 10.0, 25.0},
  {"Cold Drink", 1.0, 5.0},
  {"Milk Storage", 1.0, 4.0},
  {"Refrigerator", 2.0, 5.0},
  {"Fish Tank", 22.0, 28.0},
  {"Greenhouse", 18.0, 30.0},
  {"Server Room", 18.0, 24.0}
};

const int ITEM_COUNT = sizeof(items) / sizeof(items[0]);

int selectedItem = 1; // Default Room

String statusText = "NORMAL";


void updateAlarm()
{
  float minT = items[selectedItem].minTemp;
  float maxT = items[selectedItem].maxTemp;

  if (temperatureC > maxT)
  {
    statusText = "OVERHEAT ALERT";
    digitalWrite(BUZZER_PIN, HIGH);
  }
  else if (temperatureC < minT)
  {
    statusText = "LOW TEMP ALERT";
    digitalWrite(BUZZER_PIN, HIGH);
  }
  else
  {
    statusText = "NORMAL";
    digitalWrite(BUZZER_PIN, LOW);
  }
}

String webpage()
{
  String color = "#4CAF50";

  if(statusText == "OVERHEAT ALERT")
    color = "#F44336";

  if(statusText == "LOW TEMP ALERT")
    color = "#2196F3";

  String page;

  page += "<!DOCTYPE html><html><head>";
  page += "<meta charset='UTF-8'>";
  page += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
  page += "<meta http-equiv='refresh' content='3'>";
  page += "<title>ThermoGuard</title>";

  page += "<style>";
  page += "body{font-family:Arial;background:#f2f2f2;text-align:center;padding:15px;}";
  page += ".card{background:white;max-width:800px;margin:auto;padding:20px;border-radius:15px;box-shadow:0 0 15px rgba(0,0,0,0.2);}";
  page += ".temp{font-size:60px;font-weight:bold;color:#ff5722;}";
  page += ".status{padding:15px;border-radius:10px;color:white;font-size:22px;font-weight:bold;background:";
  page += color;
  page += ";}";
  page += "table{width:100%;border-collapse:collapse;margin-top:20px;}";
  page += "th,td{border:1px solid #ddd;padding:8px;}";
  page += "th{background:#2196F3;color:white;}";
  page += "tr:nth-child(even){background:#f9f9f9;}";
  page += "select{padding:10px;font-size:16px;}";
  page += "button{padding:10px 20px;font-size:16px;margin-top:10px;}";
  page += "</style>";

  page += "</head><body>";

  page += "<div class='card'>";

  page += "<h1>🌡 ThermoGuard</h1>";

  page += "<div class='temp'>";
  page += String(temperatureC,1);
  page += " &deg;C";
  page += "</div><br>";

  page += "<div class='status'>";
  page += statusText;
  page += "</div><br>";

  page += "<h3>Selected Material</h3>";

  page += "<form action='/set'>";

  page += "<select name='id'>";

  for(int i=0;i<ITEM_COUNT;i++)
  {
    page += "<option value='";
    page += String(i);
    page += "'";

    if(i == selectedItem)
      page += " selected";

    page += ">";
    page += items[i].name;
    page += "</option>";
  }

  page += "</select><br>";
  page += "<button type='submit'>Apply</button>";
  page += "</form>";

  page += "<h3>Allowed Range</h3>";
  page += String(items[selectedItem].minTemp);
  page += "°C to ";
  page += String(items[selectedItem].maxTemp);
  page += "°C";

  page += "<hr>";

  page += "<h3>ESP32 IP</h3>";
  page += WiFi.localIP().toString();

  page += "<h2>Daily Temperature Reference</h2>";

  page += "<table>";
  page += "<tr><th>Item</th><th>Min</th><th>Max</th></tr>";

  for(int i=0;i<ITEM_COUNT;i++)
  {
    page += "<tr>";
    page += "<td>" + items[i].name + "</td>";
    page += "<td>" + String(items[i].minTemp) + "°C</td>";
    page += "<td>" + String(items[i].maxTemp) + "°C</td>";
    page += "</tr>";
  }

  page += "</table>";

  page += "<br><b>ESP32 + DS18B20 + LCD + Buzzer</b>";

  page += "</div>";
  page += "</body></html>";

  return page;
}

void handleRoot()
{
  server.send(200, "text/html", webpage());
}

void handleSet()
{
  if(server.hasArg("id"))
  {
    int value = server.arg("id").toInt();

    if(value >= 0 && value < ITEM_COUNT)
    {
      selectedItem = value;
    }
  }

  server.sendHeader("Location","/");
  server.send(302,"text/plain","");
}

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

  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);

  Wire.begin(21,22);

  lcd.init();
  lcd.backlight();

  lcd.setCursor(0,0);
  lcd.print("ThermoGuard");

  lcd.setCursor(0,1);
  lcd.print("Starting...");

  sensors.begin();

  WiFi.begin(ssid,password);

  lcd.clear();
  lcd.print("Connecting WiFi");

  while(WiFi.status()!=WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println(WiFi.localIP());

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("WiFi Connected");

  delay(2000);

  server.on("/", handleRoot);
  server.on("/set", handleSet);

  server.begin();
}

void loop()
{
  server.handleClient();

  sensors.requestTemperatures();
  temperatureC = sensors.getTempCByIndex(0);

  if(temperatureC == DEVICE_DISCONNECTED_C)
  {
    lcd.setCursor(0,0);
    lcd.print("Sensor Error   ");

    lcd.setCursor(0,1);
    lcd.print("Check Wiring   ");

    digitalWrite(BUZZER_PIN, HIGH);

    delay(1000);
    return;
  }

  updateAlarm();

  lcd.setCursor(0,0);
  lcd.print("T:");
  lcd.print(temperatureC,1);
  lcd.print((char)223);
  lcd.print("C     ");

  lcd.setCursor(0,1);

  if(statusText == "NORMAL")
    lcd.print("NORMAL         ");
  else if(statusText == "OVERHEAT ALERT")
    lcd.print("OVERHEAT!      ");
  else
    lcd.print("LOW TEMP!      ");

  delay(1000);
}