#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <RCSwitch.h>
#include "fauxmoESP.h"

#define WIFI_SSID           "meineSSID"
#define WIFI_PASS           "Meine geheimes Passwort"
#define SERIAL_BAUDRATE     115200
#define DO_TX               15
#define DO_LED_RED          0         
#define DO_LED_BLUE         2

// Geraetecodes der Funkschalter
char* housecodes[]  =       {"01101", "01001", "01001", "01001", "11011", "01101"};       // 1 2 3 4 5
char* socketcodes[] =       {"10101", "01000", "10000", "00010", "10000", "10111"};       // A B C D E
//                             [1]    Schrank  Stehlmp  LiKette  Teich      [2]  

bool switchState[6] = {false, false, false, false, false, false};                         // Fauxmo Devicestatus- Flags

RCSwitch mySwitch = RCSwitch();
fauxmoESP fauxmo;



// -----------------------------------------------------------------------------
// Wifi Setup
// -----------------------------------------------------------------------------

void wifiSetup() {

    // Set WIFI module to STA mode
    WiFi.mode(WIFI_STA);

    // Connect
    Serial.printf("[WIFI] Connecting to %s ", WIFI_SSID);
    WiFi.begin(WIFI_SSID, WIFI_PASS);

    // Wait
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(200);
    }
    Serial.println();
    Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
}

       
// -----------------------------------------------------------------------------
// MAIN Setup (Wird einmalig durchlaufen)
// -----------------------------------------------------------------------------

void setup() {
    // Init serial port and clean garbage
    Serial.begin(SERIAL_BAUDRATE);
    Serial.println("nach Verbindungsaufbau ALEXA bitten Device <devicename> ein- oder ausschalten");

    // LED
    pinMode(DO_LED_RED,  OUTPUT);
    pinMode(DO_LED_BLUE, OUTPUT);

    mySwitch.enableTransmit(DO_TX);   // RF433 Init
    delay(1000);

    // Wifi
    wifiSetup();                      // Wifi verbinden

    digitalWrite(DO_LED_RED,  HIGH);  // Init I/O
    digitalWrite(DO_LED_BLUE, HIGH);

    fauxmo.enable(true);
    
    // Fauxmo
    fauxmo.addDevice("Steckdose");    // Alexa Device einrichten (Schaltsteckdose)
    fauxmo.addDevice("Licht");        // Alexa Device einrichten (Wohnzimmerlicht)
    fauxmo.addDevice("Teich");        // Alexa Device einrichten (Teichpumpe)
    fauxmo.addDevice("Baum");         // Alexa Device einrichten (Weihnachtsbaum) 

    // fauxmoESP 2.0.0 has changed the callback signature to add the device_id, this WARRANTY
    // it's easier to match devices to action without having to compare strings.
    fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state) {       
       Serial.print("DeviceSetState: "); Serial.print(device_name); Serial.print("; "); Serial.print(device_id); 
       Serial.print("     Status: ");

       if (state) {
         Serial.println("AN");
       } else {
         Serial.println("AUS");
       }
        
       if (device_id == 0) {                                 // Schaltsteckdose
         switchState[0]= state;
         if (state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOn(housecodes[0], socketcodes[0]);
           delay(500);
           digitalWrite(DO_LED_BLUE, HIGH); 
         }

         if (!state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOff(housecodes[0], socketcodes[0]); 
           delay(500);
           digitalWrite(DO_LED_BLUE, HIGH);
         }
       }

       if (device_id == 1) {                                 // Wohnzimmerlicht
         switchState[1]= state;
         if (state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOn(housecodes[1], socketcodes[1]); 
           delay(500);
           mySwitch.switchOn(housecodes[2], socketcodes[2]); 
           delay(500);
           mySwitch.switchOn(housecodes[3], socketcodes[3]); 
           digitalWrite(DO_LED_BLUE, HIGH); 
         }

         if (!state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOff(housecodes[1], socketcodes[1]);
           delay(500); 
           mySwitch.switchOff(housecodes[2], socketcodes[2]); 
           delay(500);
           mySwitch.switchOff(housecodes[3], socketcodes[3]); 
           digitalWrite(DO_LED_BLUE, HIGH); 
         }
       }

       if (device_id == 2) {                                 // Teichpumpe
         switchState[2]= state;
         if (state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOn(housecodes[4], socketcodes[4]); 
           delay(500);
           digitalWrite(DO_LED_BLUE, HIGH); 
         }

         if (!state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOff(housecodes[4], socketcodes[4]);
           digitalWrite(DO_LED_BLUE, HIGH); 
         }
       } 

       if (device_id == 3) {                                 // Baum [2]
         switchState[3]= state;
         if (state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOn(housecodes[5], socketcodes[5]); 
           delay(500);
           digitalWrite(DO_LED_BLUE, HIGH); 
         }

         if (!state) {
           digitalWrite(DO_LED_BLUE, LOW);
           mySwitch.switchOff(housecodes[5], socketcodes[5]);
           digitalWrite(DO_LED_BLUE, HIGH); 
         }
       }     
    });
 
    
    // Callback to retrieve current state (for GetBinaryState queries)
    fauxmo.onGetState([](unsigned char device_id, const char * device_name) {
        Serial.print("DeviceSateRequest: "); Serial.print(device_name); Serial.print("; "); Serial.print(device_id); 
        return switchState[device_id];
    });
}


// -----------------------------------------------------------------------------
// Main Loop (Wird staendig durchlaufen)
// -----------------------------------------------------------------------------

void loop() {
  fauxmo.handle();

  static unsigned long last = millis();
  if (millis() - last > 5000) {
     last = millis();
     Serial.printf("[MAIN] Free heap: %d bytes\n", ESP.getFreeHeap());
  }
}