#include <SPI.h>
#include "SPIFFS.h"
#include <WiFi.h>
#include <WiFiClient.h> 
#include <HTTPClient.h>
//#include "Arduino.h"
//using namespace std;
#include <vector>

// Pin concerned by the switch of the transistor
static const uint8_t transistor = 17;

#define DEBUG             // Comment to not display messages on Serial

#include <DHT.h>
#define brocheDeBranchementDHT 1   // La ligne de communication du DHT22 sera branchée sur la pin GPIO1
#define typeDeDHT DHT22            // Ici, le type de DHT utilisé est un DHT22 (que vous pouvez changer en DHT11, DHT21, ou autre, le cas échéant)

// Instanciation de la librairie DHT
DHT dht(brocheDeBranchementDHT, typeDeDHT);

// HOME
const char* WIFI_SSID = "Livebox-8C20";            // NAME OF THE WIFI
const char* WIFI_PASS = "ebLs7q7VyETiMfja5Z";      // PASSWORD OF THE WIFI
// P20 Lolo
// const char* WIFI_SSID = "FBI-33";         // ENTRE LE NOM DU RESEAU WIFI ICI
// const char* WIFI_PASS = "mclv2fbi";           // ENTRE LE MOT DE PASSE WIFI ICI

int wifiAttempt = 0;
String URL, postData, timeStamp, ftpFileData, ftpFileHour, ftpLongTermData;

//******************************************************************************************
// Name and Size of the sensor                                                             *
String nameSensor = "WS01";                // Enter the name of the sensor ("WS01")         *
//******************************************************************************************

// Variables to read the potential value of the battery
#define potPin 34
int potValue = 0;
float batteryLevel;

// long interval = 10;        // Mesure toutes les 10 sec                                 *
long interval = 3600;         // Mesure toutes les heures                                  *

RTC_DATA_ATTR unsigned int savingCounter = 0;
RTC_DATA_ATTR unsigned int noWifiCounter = 1;
RTC_DATA_ATTR unsigned int monthNb = 1;

void setup() {
  // Slow down the CPU from 240 to 80 Mhz
  setCpuFrequencyMhz(80);

  #ifdef DEBUG
    Serial.begin(115200);
  #endif
  while (!Serial);
  Serial.println("Serial OK");

  pinMode (transistor, OUTPUT);

  if (SPIFFS.begin()) {
    Serial.println((String)"\nSPIFFS opened!");
  }
  else {
    Serial.println((String)"SPIFFS opening failed");
  }

  // Initialisation du DHT22;
  dht.begin();
  Serial.println("Valeur du DHT22");
  Serial.println("===============");

  // Turn components ON
  delay(100);
  digitalWrite(transistor, LOW);
  delay(100);

  noInterrupts();
 
  // Lecture des données
  float temperatureEnCelsius, tauxHumidite, temperatureRessentieEnCelsius;
  delay(200);
  int counter = 0, maxCounter = 50;
  do {
    temperatureEnCelsius = dht.readTemperature();   // Lecture de la température, exprimée en degrés Celsius
    tauxHumidite = dht.readHumidity();              // Lecture du taux d'humidité (en %)
    delay(100);
    counter++;
  } while ((isnan(tauxHumidite) || isnan(temperatureEnCelsius)) && counter < maxCounter);
  Serial.print("Number of trials: "); Serial.println(counter);

  // Calcul de la température ressentie
  temperatureRessentieEnCelsius = dht.computeHeatIndex(temperatureEnCelsius, tauxHumidite, false); // Le "false" est là pour dire qu'on travaille en °C, et non en °F
  
  // Affichage des valeurs
  Serial.print("Température = "); Serial.print(temperatureEnCelsius); Serial.println(" °C");
  Serial.print("Humidité = "); Serial.print(tauxHumidite); Serial.println(" %");
  Serial.print("Température ressentie = "); Serial.print(temperatureRessentieEnCelsius); Serial.println(" °C");
  Serial.println();

  interrupts();
  
  // Turn components OFF
  delay(100);
  digitalWrite(transistor, HIGH);
  delay(100);

  wifiSetup();

  sendData(nameSensor, (String)temperatureEnCelsius, (String)tauxHumidite);

  Serial.println(F("Waiting for the measurement...\n"));

  sleepAndWakeupWithRadioDisabled(interval);

}

void loop() {

}

void sleepAndWakeupWithRadioDisabled(long interval) {

  Serial.println((String)"ZZzzzz Deep sleep for " + interval + (String)" seconds...");

  WiFi.disconnect();
  delay(1);
  WiFi.mode( WIFI_OFF );
  delay(1);

  esp_sleep_enable_timer_wakeup(interval * 1000000ull);

/*  esp_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
*/
  //Go to sleep now
  Serial.println((String)"Going to sleep now");
  delay(1000);
  esp_deep_sleep_start();
  Serial.println((String)"This will never be printed");
}

void wifiSetup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin( WIFI_SSID, WIFI_PASS );

  wifiAttempt = 0;
  Serial.print((String)"Connecting Wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    wifiAttempt++;
    Serial.print(".");
    if (wifiAttempt > 20)
      break;
  }

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println(F("\nCould not connect after 10sec... "));
  }
  else {
    Serial.print(F("\nWiFi connected -> IP address: "));
    Serial.println(WiFi.localIP());    
  }
  yield();
}

void sendData(String nameSensor, String valueA, String valueB) {
  

  // -------------- DEFINE PARAMETERS --------------
  ftpFileData     = "DB_" + nameSensor + "D.txt";
  ftpLongTermData = "DB_" + nameSensor + "_Month-" + (String)monthNb + ".txt";
  // ------------------ PARAMETERS -----------------



  // -------------------------- Saving data locally  --------------------------
  savingCounter++;
  String longTermSave = "";
  longTermSave += (String)savingCounter + ":";
  longTermSave += valueA + ",";
  longTermSave += valueB;

  // Write data to the File system
  File fileLTd = SPIFFS.open("/" + ftpLongTermData, FILE_APPEND);

  if (fileLTd) {
    Serial.println((String)"SPIFFS fileLTd OK");
  }
  else {
    Serial.println((String)"There was an error opening the fileLTd for writing");
    return;
  }
  
  if (fileLTd.println(longTermSave)) {
    Serial.println((String)"Data was saved to file system for long term storing");
  } else {
    Serial.println((String)"Long term data couldn't be saved on file system!!");
  }
  fileLTd.close();
  // -------------------------- Data saved locally  --------------------------



  // -------------------------- Sending data if WiFi  --------------------------
  if (WiFi.status() == WL_CONNECTED) {

    URL = "http://192.168.1.21/data/hH_WS.php";
    postData = "name=" + nameSensor + "&temp=" + valueA + "&humid=" + valueB + "&press=0.0&pluvio=0.0&anemo=0.0&gir=0.0&lumino=0.0";
    
    HTTPClient http;
    http.begin(URL);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    int httpCode = http.POST(postData);
    String payload = http.getString();

    Serial.print("URL : "); Serial.println(URL); 
    Serial.print("Data: "); Serial.println(postData);
    Serial.print("httpCode: "); Serial.println(httpCode);
    Serial.print("payload : "); Serial.println(payload);
    Serial.println("--------------------------------------------------");

    Serial.println(F("Data sent..."));

    noWifiCounter = 1;
  }
  // ------------------------------ All data sent by WiFi -----------------------------

  // ... else, write data to File System if no WiFi or problem with the ftp connection
  else {
    noWifiCounter++;
    String dataToSave = "";
    dataToSave += valueA + "\n";
    dataToSave += valueB;

    // Write data to the File system
    File file = SPIFFS.open("/" + ftpFileData, FILE_APPEND);

    if (!file) {
      Serial.println((String)"There was an error opening the file for writing");
      return;
    }
    else {
      Serial.println((String)"SPIFFS file OK");
//      listFileSystem("/");
    }
    
    if (file.println(dataToSave)) {
      Serial.println((String)"Data was saved to file system since no Wifi");
//      listFileSystem("/");
    } else {
      Serial.println((String)"No Wifi but data couldn't be saved on file system!!");
    }
    file.close();

  }
  
}