#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <LittleFS.h>

#ifndef STASSID
#define STASSID "Kiwi"
#define STAPSK  "ZeKiwi127"
#endif

// FP status info LittleFS
#define FP_STATUS "/fp_status.txt"

const char* ssid = STASSID;
const char* password = STAPSK;
File Status_File;

// Configuration des IO
const uint16_t ALT_POS = 13; // Broche pilotant l'alternance positive
const uint16_t ALT_NEG = 14; // Broche pilotant l'alternance négative

const uint8_t DEFAULT_PILOTE_STATUS = 1; // Mode par défaut Eco de manière à ce que la LED passe en orange après entrée d'une configuration valide


unsigned int fp = 0;

// Cette fonction pilote le changement d'état des sorties, de la LED bicolore d'état et le mémorise dans le fichier d'état
void Pilote (int Status) {
    switch (Status) {
      case 0 : // aucune alternance en sortie, LED allumée en rouge : Confort
        Serial.println("Confort");
        digitalWrite(ALT_NEG,LOW);
        digitalWrite(ALT_POS,LOW);
        break;
      case 1 : // pleine alternance en sortie, LED allumée en orange (rouge+vert) : Eco
        Serial.println("Eco");
        digitalWrite(ALT_NEG,HIGH);
        digitalWrite(ALT_POS,HIGH);
        break;
      case 2 : // demie alternance négative en sortie, LED allumée en vert : Hors Gel
        Serial.println("Hors Gel");
        digitalWrite(ALT_NEG,HIGH);
        digitalWrite(ALT_POS,LOW);
        break;
      case 3 : // demie alternance positive en sortie, LED éteinte : Arrêt
        Serial.println("Arrêt");
        digitalWrite(ALT_NEG,LOW);
        digitalWrite(ALT_POS,HIGH);
        break;
   }
    // Mémorisation dans le fichier
    Serial.print(F("Status écrit : "));
    Serial.println(Status);
    Status_File = LittleFS.open(FP_STATUS, "w+");
    Status_File.write(Status);
    Status_File.seek(0, SeekSet);
    Serial.print(F("Status relu : "));
    Serial.println(Status_File.read());
    Status_File.close();
}

// Setup OTA Stuff
void setupOTA() {
    // Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  //ArduinoOTA.setHostname("myesp8266");

  // No authentication by default
  ArduinoOTA.setPassword("12345");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_FS
      type = "filesystem";
    }

    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.begin();
}

// Setup LittleFS
void setupLFS() {
  Serial.println(F("Initializing FS..."));
  if (LittleFS.begin()) {
    Serial.println(F("LittleFS system mounted with success"));
  } else {
    Serial.println(F("An Error has occurred while mounting LittleFS"));
  }

  // Get all information about LittleFS
  FSInfo fsInfo;
  LittleFS.info(fsInfo);

  Serial.println("------------------------------");
  Serial.println("File system info");
  Serial.println("------------------------------");
  
  // Taille de la zone de fichier
  Serial.print("Total space:      ");
  Serial.print(fsInfo.totalBytes);
  Serial.println(" byte");

  // Espace total utilise
  Serial.print("Total space used: ");
  Serial.print(fsInfo.usedBytes);
  Serial.println(" byte");

  // Taille d un bloc et page
  Serial.print("Block size:       ");
  Serial.print(fsInfo.blockSize);
  Serial.println(" byte");

  Serial.print("Page size:        ");
  Serial.print(fsInfo.totalBytes);
  Serial.println(" byte");

  Serial.print("Max open files:   ");
  Serial.println(fsInfo.maxOpenFiles);

  // Taille max. d un chemin
  Serial.print("Max path lenght:  ");
  Serial.println(fsInfo.maxPathLength);

  Serial.println();

  Serial.println("------------------------------");
  Serial.println("List files");
  Serial.println("------------------------------");
  // Ouvre le dossier racine | Open folder
  Dir dir = LittleFS.openDir("/");
  // Affiche le contenu du dossier racine | Print dir the content
  while (dir.next()) {
    // recupere le nom du fichier | get filename
    Serial.print(dir.fileName());
    Serial.print(" - ");
    // et sa taille | and the size
    if (dir.fileSize()) {
      File file = dir.openFile("r");
      Serial.print(file.size());
      Serial.println(" byte");
      file.close();
    } else {
      File file = dir.openFile("r");
      if ( file.isDirectory() ) {
        Serial.println("this is a folder");
      } else {
        Serial.println("file is empty");
      }
      file.close();
    }
  }
}

void fp_from_fs() {
    unsigned int Num_Cde;
    
    if (!LittleFS.exists(FP_STATUS)) {
      Serial.println("Fil Pilot status file does not exists. Create it");
      Status_File = LittleFS.open(FP_STATUS, "w");
      Status_File.write(DEFAULT_PILOTE_STATUS);
      Status_File.close();
      Pilote(DEFAULT_PILOTE_STATUS);
      return;
    }
    // File should exist so read it
    Serial.println(F("Status FP from FS  : "));
    Status_File = LittleFS.open(FP_STATUS, "r");
    Num_Cde = Status_File.read();
    Status_File.close();
    Serial.print(F("Status is : "));
    Serial.println(Num_Cde);

    Pilote(Num_Cde);
}

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
  
  // Setup OTA
  setupOTA();

  // Setup LittleFS
  setupLFS();
  
  // Alternance -
  pinMode(ALT_NEG, OUTPUT);
  // Alternance +
  pinMode(ALT_POS, OUTPUT);

  // Now retreive FP status from FS
  fp_from_fs();

  // We are ready
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  
}

void loop() {
  Pilote(fp);
  fp = fp + 1;
  if (fp >= 4) {
    fp = 0;
  }
  delay(30000);
  ArduinoOTA.handle();
}
