#define BLYNK_TEMPLATE_ID "TMPL2A2GnRrGR"
#define BLYNK_TEMPLATE_NAME "Controlador"
#define BLYNK_AUTH_TOKEN "DIeVGcGHnZzUDzJsksxpJ8rZq4J8Iov-"

#include <WiFiManager.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <BlynkSimpleEsp32.h>
#include <WiFiUdp.h>     // For OTA
#include <ArduinoOTA.h>  // For OTA
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "freertos/queue.h"

#define BLYNK_PRINT Serial
#include <SPI.h>

hw_timer_t *timer1 = NULL; //faz o controle do temporizador (interrupção por tempo)

int DeviceLED = 2;
int pinoSensor = 4;
int ReCnctFlag;       // Reconnection Flag
int ReCnctCount = 0;  // Reconnection counter
unsigned long anterior = 0;

BlynkTimer timer;

int RELAY_PIN_[] = { 32, 33, 25, 26,27,14, 23, 22, 21, 18, 19, 5, 17, 16, 4, 0, 15 };

int numero_pinos = 18;  // Variavel usada nos loops for, coloca a quantidade de pinos iniciando da posição 0

//Pinos Validos  == 33,32,25,26,27,14,12,13,23,22,21,18,19,5,17,16,4,0,2,15//
// Não usar pino 12 quando conectar 5V
int secao[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int numero_secoes = 3;

unsigned long previousMillis = 0;
unsigned long interval = 30000;
bool controle = true;  // variavel que ira controlar quando uma tarefa deve ser finalizada

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "";
char pass[] = "";


struct PinData {
  int pinNumber;
  int pinValue;
};

PinData pinsToMonitor[] = {
  { V0, 0 }, { V1, 0 }, { V2, 0 }, { V3, 0 }, { V4, 0 }, { V5, 0 }, { V6, 0 }, { V7, 0 }, { V8, 0 }, { V9, 0 }, { V10, 0 }, { V11, 0 }, { V12, 0 }, { V13, 0 }, { V14, 0 }
};




BLYNK_WRITE_DEFAULT() {
  for (int i = 0; i < sizeof(pinsToMonitor) / sizeof(PinData); i++) {
    if (request.pin == pinsToMonitor[i].pinNumber) {
      pinsToMonitor[i].pinValue = param.asInt();
      if (pinsToMonitor[i].pinValue == 1) {
        digitalWrite(RELAY_PIN_[i], LOW);
      } else {
        digitalWrite(RELAY_PIN_[i], HIGH);
      }
      break;
    }
  }
}

BLYNK_CONNECTED() {
  Serial.println("Cconnected");

  Blynk.syncVirtual(V0);
  Blynk.syncVirtual(V1);
  Blynk.syncVirtual(V2);
  Blynk.syncVirtual(V3);
  Blynk.syncVirtual(V4);
  Blynk.syncVirtual(V5);
  


  ReCnctCount = 0;
}

void UpTime() {
  Blynk.virtualWrite(V14, millis() / 1000);  // Send UpTime seconds to App
  Serial.print("UpTime: ");
  Serial.println(millis() / 1000);                   // Send UpTime seconds to Serial
  digitalWrite(DeviceLED, !digitalRead(DeviceLED));  // Blink onboard LED
}

#include "funcoes.h"

void setup() {

  for (int i = 0; i <= numero_pinos; i++) {
    pinMode(RELAY_PIN_[i], OUTPUT);
    digitalWrite(RELAY_PIN_[i], HIGH);
    delay(50);
  }
  pinMode(pinoSensor, INPUT); //DEFINE O PINO COMO ENTRADA

  Serial.begin(115200);
  pinMode(DeviceLED, OUTPUT);
  //(ler_sensor, "Ler sensor", configMINIMAL_STACK_SIZE + 2000, NULL, 2, NULL,2);

  WiFi.begin("Wokwi-GUEST", "", 6);

  WiFiManager wifiManager;
  wifiManager.setConfigPortalTimeout(180);
  wifiManager.autoConnect("Sistema Irrigacao");
  Blynk.config(auth);
  Blynk.connect();
  timer.setInterval(1000L, UpTime);
  Blynk.virtualWrite(V14, millis() / 1000);

  ArduinoOTA.setHostname("Loss of connection test");  // For OTA
  ArduinoOTA.begin();                                 // For OTA
  Blynk.virtualWrite(V21, 1);   //manda um pro led 
  Blynk.virtualWrite(V9, 0);    // Manda zero pra variavel aconar rega
  Blynk.virtualWrite(V10, 0);
  Blynk.virtualWrite(V22, "Sistema liberado");
  Inicia_Whachdog ();
}

void loop() {
  timerWrite(timer1, 0); //reseta o temporizador (alimenta o watchdog)
  timer.run();
  ArduinoOTA.handle();  // For OTA
  unsigned long currentMillis = millis();
  unsigned long tempo = millis();
  cria_tarefa();
  
  if (tempo - anterior > 60000){
     anterior = tempo;
     ler_sensor();
  }

  if (Blynk.connected()) {  // If connected run as normal
    Blynk.run();
  } else if (ReCnctFlag == 0) {  // If NOT connected and not already trying to reconnect, set timer to try to reconnect in 30 seconds
    ReCnctFlag = 1;              // Set reconnection Flag
    Serial.println("Starting reconnection timer in 30 seconds...");
    timer.setTimeout(30000L, []() {  // Lambda Reconnection Timer Function
      ReCnctFlag = 0;                // Reset reconnection Flag
      ReCnctCount++;                 // Increment reconnection Counter
      Serial.print("Attempting reconnection #");
      Serial.println(ReCnctCount);
      Blynk.connect();  // Try to reconnect to the server
    });                 // END Timer Function
  }
  if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >= interval)) {
    Serial.print(millis());
    Serial.println("Reconnecting to WiFi...");
    WiFi.disconnect();
    WiFi.reconnect();
    previousMillis = currentMillis;
  }
    
   vTaskDelay(100 / portTICK_PERIOD_MS);
}