#include <ESPAsyncWebServer.h>
#include <WiFi.h>

// Wi-Fi credentials
const char* ssid = "Your_SSID";
const char* password = "Your_PASSWORD";

// Define water level buttons
#define WATER_LOW_BUTTON 6
#define WATER_MEDIUM_BUTTON 7
#define WATER_HIGH_BUTTON 8
#define WATER_EMPTY_BUTTON 9

AsyncWebServer server(80);

// Water control variables
bool waterRunning = false;
bool draining = false;
unsigned long waterDuration = 0;
unsigned long waterStartTime = 0;

String getWaterLevelStatus() {
  if (digitalRead(WATER_EMPTY_BUTTON) == HIGH) return "Empty";
  if (digitalRead(WATER_LOW_BUTTON) == HIGH) return "Low";
  if (digitalRead(WATER_MEDIUM_BUTTON) == HIGH) return "Medium";
  if (digitalRead(WATER_HIGH_BUTTON) == HIGH) return "High";
  return "Unknown";
}

// Function to calculate remaining time
unsigned long getRemainingTime() {
  if (waterRunning) {
    unsigned long elapsed = millis() - waterStartTime;
    if (elapsed >= waterDuration) {
      waterRunning = false; // Stop operation if complete
      return 0;
    }
    return (waterDuration - elapsed) / 1000; // Convert to seconds
  }
  return 0;
}

// Start water operation
void startWater(int mode, bool isDraining) {
  if (!waterRunning) {
    unsigned long durations[] = {120000, 180000, 240000, 300000}; // 2, 3, 4, 5 min durations

    waterRunning = true;
    draining = isDraining;
    waterStartTime = millis();
    waterDuration = isDraining ? durations[3] : durations[mode - 1]; // Draining uses the last value

    if (isDraining) {
      digitalWrite(WATER_DRAIN, HIGH);
    } else {
      digitalWrite(WATER_VALVE, HIGH);
    }
  }

  // Stop the operation if time has elapsed
  if (waterRunning && (millis() - waterStartTime >= waterDuration)) {
    if (isDraining) {
      digitalWrite(WATER_DRAIN, LOW);
    } else {
      digitalWrite(WATER_VALVE, LOW);
    }
    waterRunning = false;
  }
}

void handleWaterButton() {
  if (digitalRead(WATER_EMPTY_BUTTON) == HIGH) {
    startWater(0, true); // Empty water
    return;
  }

  int waterButtons[] = {
    WATER_LOW_BUTTON,
    WATER_MEDIUM_BUTTON,
    WATER_HIGH_BUTTON
  };

  for (int i = 0; i < 3; i++) {
    if (digitalRead(waterButtons[i]) == HIGH) {
      startWater(i + 1, false); // Fill water based on level
      break;
    }
  }
}

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

  pinMode(WATER_LOW_BUTTON, INPUT);
  pinMode(WATER_MEDIUM_BUTTON, INPUT);
  pinMode(WATER_HIGH_BUTTON, INPUT);
  pinMode(WATER_EMPTY_BUTTON, INPUT);

  pinMode(WATER_VALVE, OUTPUT);
  pinMode(WATER_DRAIN, OUTPUT);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to Wi-Fi...");
  }
  Serial.println("Connected to Wi-Fi");
  Serial.println(WiFi.localIP());

  // Route to fetch status and remaining time
  server.on("/status", HTTP_GET, [](AsyncWebServerRequest* request) {
    String status = getWaterLevelStatus();
    unsigned long remainingTime = getRemainingTime();
    request->send(200, "application/json", 
      "{\"water_level\": \"" + status + 
      "\", \"remaining_time\": \"" + String(remainingTime) + "\"}");
  });

  // Route to serve the main page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
    request->send(200, "text/html", R"rawliteral(
      <!DOCTYPE html>
      <html>
      <head>
        <title>Water Level & Remaining Time</title>
        <script>
          async function fetchStatus() {
            const response = await fetch('/status');
            const data = await response.json();
            document.getElementById('status').innerText = data.water_level;
            document.getElementById('time').innerText = data.remaining_time + " seconds";
          }
          setInterval(fetchStatus, 1000); // Refresh every second
        </script>
      </head>
      <body>
        <h1>Water Level Status</h1>
        <p>Current Status: <span id="status">Loading...</span></p>
        <p>Remaining Time: <span id="time">Loading...</span></p>
      </body>
      </html>
    )rawliteral");
  });

  server.begin();
}

void loop() {
  handleWaterButton();
}