// Uncomment the following line to enable serial debug output
//#define ENABLE_DEBUG

#ifdef ENABLE_DEBUG
#define DEBUG_ESP_PORT Serial
#define NODEBUG_WEBSOCKETS
#define NDEBUG
#endif

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include "SinricPro.h"
#include "SinricProSwitch.h"

#define WIFI_SSID "<Your Wifi SSD(Name) here>"
#define WIFI_PASS "<Your Wifi Password here>"
#define APP_KEY "<Sinric Pro Account API KEY>"        // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "<Sinric Pro Account APP Secret>"  // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define SWITCH_ID "<Switch id created in sinric pro>" // Should look like "5dc1564130xxxxxxxxxxxxxx"
#define BAUD_RATE 9600                                // Change baudrate to your need

#define CONTROL_PIN1 D1      // GPIO for control input 1
#define CONTROL_PIN2 D2      // GPIO for control input 2
#define WIFI_PIN LED_BUILTIN // GPIO for WIFI LED (inverted)
#define VALVE_STATUS_PIN D7  // GPIO for valve status
#define TIMEOUT 30           // valve power timeout
#define BUTTON_TIMEOUT 1000  // minimum time the button should wait to change the state back

bool isValveOpen = false; // Variable to track valve status
unsigned long lastBtnPress = 0;

// function to make control pins 0 0 ( cut off supply ).
void cutSupplyToValve()
{
    digitalWrite(CONTROL_PIN1, LOW);
    digitalWrite(CONTROL_PIN2, LOW);
    Serial.println("Valve supply is cut off");
}

// Change D1, D2 to 1 0 for 25ms ( Open valve )
void openValve()
{
    Serial.println("Opening valve");
    digitalWrite(CONTROL_PIN1, HIGH);
    digitalWrite(CONTROL_PIN2, LOW);
    digitalWrite(VALVE_STATUS_PIN, HIGH);
    isValveOpen = 1;
    delay(TIMEOUT);
    cutSupplyToValve();
}

// Change D1, D2 to 0 1 for 25ms ( Close valve )
void closeValve()
{
    Serial.println("Closing valve");
    digitalWrite(CONTROL_PIN1, LOW);
    digitalWrite(CONTROL_PIN2, HIGH);
    digitalWrite(VALVE_STATUS_PIN, LOW);
    isValveOpen = 0;
    delay(TIMEOUT);
    cutSupplyToValve();
}

//  Callback for device
bool onPowerState(const String &deviceId, bool &state)
{
    Serial.printf("Device %s turned %s (via SinricPro) \r\n", deviceId.c_str(), state ? "on" : "off");
    state ? openValve() : closeValve();
    return true; // request handled properly
}

// setup function for WiFi connection
void setupWiFi()
{
    Serial.printf("\r\n[Wifi]: Connecting");
    WiFi.begin(WIFI_SSID, WIFI_PASS);

    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.printf(".");
        delay(250);
    }
    Serial.printf("connected!\r\n[WiFi]: IP-Address is %s\r\n", WiFi.localIP().toString().c_str());
}

// setup function for SinricPro
void setupSinricPro()
{
    // add device to SinricPro
    SinricProSwitch &mySwitch = SinricPro[SWITCH_ID];

    // set callback function to device
    mySwitch.onPowerState(onPowerState);

    // setup SinricPro
    SinricPro.onConnected([]()
                          { Serial.printf("Connected to SinricPro\r\n"); });
    SinricPro.onDisconnected([]()
                             { Serial.printf("Disconnected from SinricPro\r\n"); });
    // SinricPro.restoreDeviceStates(true); // Uncomment to restore the last known state from the server.
    SinricPro.begin(APP_KEY, APP_SECRET);
}

// main setup function
void setup()
{
    pinMode(WIFI_PIN, OUTPUT);         // define LED GPIO as output
    pinMode(CONTROL_PIN1, OUTPUT);     // control pin
    pinMode(CONTROL_PIN2, OUTPUT);     // control pin
    pinMode(VALVE_STATUS_PIN, OUTPUT); // valve status pin

    Serial.begin(BAUD_RATE);
    Serial.printf("\r\n\r\n");
    setupWiFi();
    setupSinricPro();
}

void loop()
{
    SinricPro.handle();
}