#include <WiFiS3.h>

// ========== Network Configuration ==========
const char* ssid = "ESP32_AP";
const char* password = "12345678";
const char* serverIP = "192.168.4.1";
const int serverPort = 8080;

// ========== Button Pins ==========
const int BTN_RGB_ON    = 2;
const int BTN_RGB_OFF   = 3;
const int BTN_RGB_COLOR = 4;
const int BTN_BUZZ_ON   = 5;
const int BTN_BUZZ_OFF  = 6;

const int btnPins[] = {BTN_RGB_ON, BTN_RGB_OFF, BTN_RGB_COLOR, BTN_BUZZ_ON, BTN_BUZZ_OFF};
const char* btnCmds[] = {"RGB_ON", "RGB_OFF", "RGB_COLOR", "BUZZ_ON", "BUZZ_OFF"};

WiFiClient client;
unsigned long lastReconnectAttempt = 0;

// ========== Debounce Variables (Key Fix) ==========
bool lastReading[5] = {HIGH, HIGH, HIGH, HIGH, HIGH};  // Last raw reading values
bool buttonState[5] = {HIGH, HIGH, HIGH, HIGH, HIGH};  // Stable state
unsigned long lastDebounceTime[5] = {0, 0, 0, 0, 0};
const unsigned long debounceDelay = 50;

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; }
  delay(1000);

  for (int i = 0; i < 5; i++) {
    pinMode(btnPins[i], INPUT_PULLUP);
  }

  Serial.println("\n=== UNO R4 Remote Controller ===");

  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("WiFi module not found!");
    while (true);
  }

  Serial.print("Connecting WiFi");
  WiFi.begin(ssid, password);
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 30) {
    delay(500);
    Serial.print(".");
    attempts++;
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("\nWiFi connected, IP: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("\nWiFi connection failed!");
  }
}

void connectToServer() {
  Serial.print("Connecting to ESP32...");
  if (client.connect(serverIP, serverPort)) {
    Serial.println("Success!");
    client.println("REMOTE_CONNECTED");
  } else {
    Serial.println("Failed, retrying in 5 seconds");
  }
}

void sendCommand(const char* cmd) {
  if (client.connected()) {
    client.println(cmd);
    Serial.print("[Sent] ");
    Serial.println(cmd);
  } else {
    Serial.println("[Error] Not connected, command not sent");
  }
}

// ========== Fixed Button Detection ==========
void checkButton(int index) {
  bool reading = digitalRead(btnPins[index]);

  // If reading value changes, reset debounce timer
  if (reading != lastReading[index]) {
    lastDebounceTime[index] = millis();
  }

  // Debounce time elapsed, update stable state
  if ((millis() - lastDebounceTime[index]) > debounceDelay) {
    if (reading != buttonState[index]) {
      buttonState[index] = reading;

      // Press event (low level, because INPUT_PULLUP is used)
      if (buttonState[index] == LOW) {
        Serial.print("[Button] ");
        Serial.println(btnCmds[index]);
        sendCommand(btnCmds[index]);
      }
    }
  }

  lastReading[index] = reading;
}

void loop() {
  // Maintain TCP connection
  if (!client.connected()) {
    if (millis() - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = millis();
      connectToServer();
    }
  }

  // Check 5 buttons
  for (int i = 0; i < 5; i++) {
    checkButton(i);
  }

  // Receive ESP32 feedback
  if (client.connected() && client.available()) {
    String response = client.readStringUntil('\n');
    response.trim();
    Serial.print("[Received] ");
    Serial.println(response);
  }
}
