/*
	20.06.2025
	WiFi Manager für IoT  ohne WebServer für ESP8266 und ESP32
	siehe RandomNerdTutorial und DeepSeek
  mit Built-In-LED und Taster an GPIO14 (D5)
  mit OLED
 
  Bei Tastendruck an GPIO14 (D5) zu Masse mit Restart, wird der Wifi_Manager Start erzwungen.
  192.168.4.1 lebt nur 5 Min.
  
  keine zusätzlichen Parameter

*/

#if defined(ESP8266)
  #define WIFI_BUTTON_PIN 14  // Taster an GPIO14 (D5)
  #define LED_PIN 2           // D4 = GPIO2 (Built-in LED)
#elif defined(ESP32)
  #define WIFI_BUTTON_PIN 14  // Taster an GPIO14 (D5)
  #define LED_PIN 2           // GPIO2 (Built-in LED)
#endif

#include <WiFiManager.h>    // von Tzapu
WiFiManager wifiManager;

#define AP_SSID    "ESP_AP_Config"

int rssi = 0;

void startWiFi_Manager() {

  pinMode(WIFI_BUTTON_PIN, INPUT_PULLUP);  // Taster mit internem Pull-up
  pinMode(LED_PIN, OUTPUT);                // LED für Status

  // Kurzes LED-Blinken zum Start
  digitalWrite(LED_PIN, LOW);   // ein
  delay(200);
  digitalWrite(LED_PIN, HIGH);  // aus
  delay(200);

  // Uncomment and run it once, if you want to erase all the stored information
  //wifiManager.resetSettings();

  // set custom ip for portal
  //wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));

  // Timeout für das Konfigurationsportal setzen (300 Sekunden)
  wifiManager.setConfigPortalTimeout(300);  // Timeout in sek: 5 Minuten

  // Callback für den AP-Modus die beim Start des AP-Modus aufgerufen wird.
  wifiManager.setAPCallback([](WiFiManager* wm) {
    Serial.println("Config-Portal gestartet! SSID: " + wm->getConfigPortalSSID());

    snprintf(line1, sizeof(line1), "Start AccessPoint:");  // Überschreibt line1 , Zeichenlänge 30 wird geprüft
    snprintf(line2, sizeof(line2), "%s", wm->getConfigPortalSSID().c_str() );
    IPAddress apIP = WiFi.softAPIP();         // IP-Adresse des AP formatieren
    snprintf(line3, sizeof(line3), "AP-IP: %s", apIP.toString().c_str() );      // AP - IP 192.168.4.1
    snprintf(line4, sizeof(line4), "");  // 
    snprintf(line5, sizeof(line5), "");  // 
    showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"  
  });

  // Callback nach erfolgreicher Konfiguration
  wifiManager.setSaveConfigCallback([]() {
    Serial.println("WLAN-Daten gespeichert!");
    rssi = WiFi.RSSI();

    snprintf(line3, sizeof(line3), "WLAN - Daten");  // 
    snprintf(line4, sizeof(line4), "gespeichert.");  // 
    snprintf(line5, sizeof(line5), "");  // 
    showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"  

    ESP.restart();  // Neustart mit gespeicherten neuen WLAN-Daten
  });

  // Wenn Taster gedrückt (LOW), starte Config-Portal
  if (digitalRead(WIFI_BUTTON_PIN) == LOW) {
    delay(500);  // Entprellen
    if (digitalRead(WIFI_BUTTON_PIN) == LOW) {
      snprintf(line5, sizeof(line5), "** Release Button **");  // 
      showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"  

      while(digitalRead(WIFI_BUTTON_PIN) == LOW) {      // Warten bis Taste wieder losgelassen.
        delay(500);  // Kurze Verzögerung zur CPU-Entlastung
      }
      digitalWrite(LED_PIN, LOW);  // LED ein = Config-Modus
      Serial.println("Starte Config-Portal...");

      wifiManager.startConfigPortal(AP_SSID);  // AP mit SSID "ESP-Config"

      digitalWrite(LED_PIN, HIGH);  // LED aus = Fertig
    }
  }

  // Automatische Verbindung mit ssid und pass vom eeprom versuchen, sonst start mit Access Point AP
  if (!wifiManager.autoConnect(AP_SSID)) {
    Serial.println("Fehler: Keine Verbindung und Timeout erreicht!\tESP restart");

    snprintf(line4, sizeof(line4), "Keine WiFi-Verbindg");  // 
    snprintf(line5, sizeof(line5), "    Press Button");  // 
    showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"   

    ESP.restart();  // Neustart bei Fehler
  }

  digitalWrite(LED_PIN, HIGH);  // LED aus = Fertig
  Serial.println("Erfolgreich verbunden mit: " + WiFi.SSID());
  rssi = WiFi.RSSI();

  if (rssi < -80) {  // Schlechtes Signal
    Serial.println("Schwaches WiFi-Signal!");
  } else {
    Serial.print("WiFi-Signal ");   Serial.print(rssi); Serial.println(" dB");
  }

  snprintf(line1, sizeof(line1), "SSID: %s", WiFi.SSID().c_str());  // SSID ausgeben
  snprintf(line2, sizeof(line2), "IP: %s", WiFi.localIP().toString().c_str());  // IP ausgeben
  snprintf(line3, sizeof(line3), "mac: %s", WiFi.macAddress().c_str());   // MQTT-Label
  snprintf(line4, sizeof(line4), "** connected **");      // 
  snprintf(line5, sizeof(line5), "Signal: %sdB", String(rssi));  //
  showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"     

}

//----------- Prüft die WLAN-Verbindung und stellt diese wieder her, wenn Fehler
void checkWiFiConnection() {
  Serial.print("Checking WiFi... ");
  snprintf(line4, sizeof(line4), "** connected **");      // 
  snprintf(line5, sizeof(line5), "Checking WiFi...");  //
  showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"     

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi getrennt! Versuche Reconnect... ");
    snprintf(line4, sizeof(line4), "** reconnect **");      // 
    snprintf(line5, sizeof(line5), "Checking WiFi...");  //
    showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h" 

    WiFi.reconnect();  // Neu verbinden

    // Automatische Verbindung mit ssid und pass vom eeprom versuchen, sonst start mit Access Point AP
    if (!wifiManager.autoConnect(AP_SSID)) {
      Serial.println("Fehler: Keine Verbindung und Timeout erreicht!\tESP restart");
      snprintf(line4, sizeof(line4), "** WiFi lost **");      // 
      snprintf(line5, sizeof(line5), "ESP restart...");  //
      showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h" 

      ESP.restart();  // Neustart bei Fehler
    } else {
      rssi = WiFi.RSSI();
      Serial.println("WiFi verbunden! IP: " + WiFi.localIP().toString());
      Serial.println("Signalstärke (RSSI): " + String(rssi) + " dB");

      snprintf(line1, sizeof(line1), "SSID: %s", WiFi.SSID().c_str());  // SSID ausgeben
      snprintf(line2, sizeof(line2), "IP: %s", WiFi.localIP().toString().c_str());  // IP ausgeben
      snprintf(line3, sizeof(line3), "mac: %s", WiFi.macAddress().c_str());   // MQTT-Label
      snprintf(line4, sizeof(line4), "** connected **");      // 
      snprintf(line5, sizeof(line5), "Signal: %sdB", String(rssi));  //
      showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"           
    }
  } else {    // WiFi connected, kein Problem
    rssi = WiFi.RSSI();
    Serial.println("WiFi ok!\t" + String(rssi) + " dB");

    snprintf(line4, sizeof(line4), "** connected **");      // 
    snprintf(line5, sizeof(line5), "Signal: %sdB", String(rssi));  //
    showTextOLED(lines, 5);       // siehe "myOLED_u8g2.h"               
  }
}
