/***********************************************************************************************************************************************************
* Sous Programme V2 : Initialisation de la connexion Ethernet                             --- #include Ethernet.h 
* Fonction : Connexion Ethernet avec le Shield Ethernet 2
* en IP Fixe ou DHCP   (Variable DHCP)
* Declaration du Ethernet Shield 2
*
************************************************************************************************************************************************************
* Entree : Variable DHCP = 1 ou 0 (IP Fixe), mac , ip Masque sous reseau, Gateway, DNS 
*  conf.ip, conf.gateway, conf.subnet, DNS0, DNS1
*  Affichage OK() FAILED() VIDE()
*
* Sortie : Serial Print
*  etatWAN : variable globale --> Test du DNS de google : WAN passerelle OK !!!!  1 OK // 0 Down
*  dhcpEtat : Etat du mode de la carte reseau ( basculement automatique en mode dhcp si l a la configuration reseau de l'Arduino est fausse)
*  Test de validite de l'adresse IP
*  
************************************************************************************************************************************************************/
boolean TestValidityIPadress();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Initialisation_Ethernet()
{
// Initialisation de la Liaison Ethernet avec le Module Ethernet 2 [      ]
Serial.println(); OK();  Serial.println(F("## Initialisation Ethernet v2 : START ......."));

//Ethernet.hostname("PriseIP_UNO_R4");                                                                          
//Serial.println(Ethernet.hostname());
//Ethernet.hostname(conf.nameSystem);
  
  // Configuration MAC Address 
  OK();  Serial.println(F("- MAC Address Physique du Module Ethernet v2 : DE:AD:BE:EF:FE:B1 ")); 
  OK();  Serial.print  (F("- MAC Address actuelle du Module Ethernet v2 : ")); PrintMAC(conf.mac); Serial.println(); 
  // Test si l'adresse MC a ete changer --> Attention si plusieurs Arduino UNO avec la meme adresse MAC sur les reseaux risque de BUG 
  if ( conf.mac[0] == default_conf.mac[0] && conf.mac[1] == default_conf.mac[1] && conf.mac[2] == default_conf.mac[2] && conf.mac[3] == default_conf.mac[3] && conf.mac[4] == default_conf.mac[4] && conf.mac[5] == default_conf.mac[5] )
    {Serial.println(F("[      ]  \033[;37;41m###     ATTENTION  !!! ###     : Il Faut changer l'adresse MAC de l'Arduino UNO R4 \033[0;39;49m"));  Serial.println(); } 
 
// Connect to Ethernet network
  VIDE();  Serial.println(F("## START Connexion Ethernet :"));
  //Ethernet.begin(conf.mac, conf.ip);

  VIDE();  Serial.println(F("   - Initialisation IP : Fixe ou DHCP ...."));
// Configuration : IP Fixe ou DHCP
  if (conf.dhcp == 0) 
     { 
        
		OK(); Serial.println(F("   - Configuration IP : IP Fixe"));        // Ethernet.config(conf.ip, DNS, conf.gateway,   conf.subnet);             //Ethernet.config(conf.ip, conf.gateway, conf.subnet, DNS0, DNS1);
        Ethernet.init(10);                                                                                                   // CS du W5500
        Ethernet.begin(conf.mac, conf.ip, myDNS, conf.gateway, conf.subnet);
        delay(100);

        VIDE();  Serial.println(F("   - Test de validite de l'adresse IP <--> Passerelle en fonction du masque de sous reseau : "));
        boolean testValidityIP;
        testValidityIP = TestValidityIPadress(conf.ip, conf.subnet, conf.gateway);
        Serial.println( testValidityIP                           ? "[ \033[1;32;40m OK \033[0;39;49m ]       o IP et Passerelle OK !" : "[\033[;37;41mFAILED\033[0;39;49m]       o Attention Erreur de configuration Resau : L'IP et la passerelle ne sont pas sur le meme reseau !");
        Serial.println( conf.subnet[3] != 255                    ? "[ \033[1;32;40m OK \033[0;39;49m ]       o Subnet OK !"           : "[\033[;37;41mFAILED\033[0;39;49m]       o Attention Erreur de configuration Resau : Masque de sous reseau Erreur !");  
        Serial.print  ( conf.ip[3] != conf.gateway[3]            ? " "                                                                : "[\033[;37;41mFAILED\033[0;39;49m]       o Attention Erreur de configuration Resau : IP et Passerelle Identique  !");  
        Serial.print  ( (conf.ip[3] != 255) || (conf.ip[3] != 0) ? " "                                                                : "[\033[;37;41mFAILED\033[0;39;49m]       o Attention Erreur de configuration Resau : IP erreur  !");  
        if ( !testValidityIP || conf.subnet[3] == 255 || conf.ip[3] == conf.gateway[3] || conf.ip[3] == 0 || conf.ip[3] == 255 ) 
		{ dhcpEtat = 1; Serial.println(F("[      ]      ooo L'Arduino UNO R4 Passe en DHCP"));   }            
     }
  else 
     {
        Serial.println(F("[      ]   - Configuration IP : DHCP")); Serial.println();
        //Ethernet.begin(conf.mac);

        dhcpEtat = false;

        if (Ethernet.begin(conf.mac) == 1) {
        dhcpEtat = true;
           OK();         Serial.println("      Mode DHCP actif");
        } else 
        {  FAILED();     Serial.println("      DHCP echoue");         }
     }  
  // ----------- Fin IP Fixe ou DHCP

// Fin Connexion au Resau Ethernet ------------------------------------------------------------------------------------------------------------------------
// --> Ethernet Connecte : Test 
  Serial.println();
  //Serial.print(F(" - Ethernet 2 : "));   Serial.println( Ethernet.isConnected() ? "OK !! Ethernet Connecte" : "ERROR : Tester les parametres Reseau IP, Passerelle" );
  VIDE();   Serial.println(F("## Satus Connexion : "));
 
switch (Ethernet.hardwareStatus()) {
  case EthernetNoHardware:      FAILED();       Serial.println("   Aucun module Ethernet detecte");
    break;
  case EthernetW5100:           OK();           Serial.println("   W5100 detecte");
    break;
  case EthernetW5200:           OK();           Serial.println("   W5200 detecte");
    break;
  case EthernetW5500:           OK();           Serial.println("   W5500 detecte");
    break;
}

switch (Ethernet.linkStatus()) {
  case Unknown:                 FAILED();       Serial.println("   Etat lien inconnu");
    break;
  case LinkON:                  OK();           Serial.println("   Lien Ethernet actif");
    break;
  case LinkOFF:                 FAILED();       Serial.println("   Pas de lien Ethernet");
    break;
}

 // print your Ethernet shield's IP address
  IPAddress ip =      Ethernet.localIP();
  IPAddress subnet =  Ethernet.subnetMask();
  IPAddress gateway = Ethernet.gatewayIP();
  //IPAddress dns1 = Ethernet.dns();

//  Ethernet.setDnsServerIP   //https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setdnsserverip/
  
  OK();  Serial.print(F("   - IP      : ")); Serial.println(ip);
  OK();  Serial.print(F("   - subnet  : ")); Serial.println(subnet);
  OK();  Serial.print(F("   - gateway : ")); Serial.println(gateway);
  OK();  Serial.print(F("   - DNS     : ")); Serial.print( myDNS[0] ); Serial.print("."); Serial.print( myDNS[1] ); Serial.print("."); Serial.print( myDNS[2] ); Serial.print("."); Serial.print( myDNS[3] );  Serial.println(); 
  Serial.println(); 


// Test DNS                                                                                               // https://forum.arduino.cc/t/resolving-host-names/317186/2
  VIDE();     Serial.println(F("## DNS Start...."));
  VIDE();     Serial.println(F("   - Test DNS : connexion www.google.fr : "));
  //DNSClient dns;                                                                            // Declarer dans prog principale
  dns.begin(Ethernet.dnsServerIP());
  if(dns.getHostByName("www.google.com",timeServer) == 1) {
    OK();     Serial.print  (F("     IP google : = "));                 Serial.println(timeServer);
    OK();     Serial.println(F("     DNS OK !"));
    etatWAN = 1;
  }
  else {
	  FAILED(); Serial.println(F("   ERROR !!! DNS lookup failed")); 
	  FAILED(); Serial.println(F("\033[;37;41m  ###     ATTENTION  !!! ###     : la connexion WAN ne fonctionne pas : Il Faut verifier les parametres reseau \033[0;39;49m"));  
	  } 
  Serial.println(); 

  
// NTP Time  
  if ( etatWAN == 1)
     {
         OK(); Serial.println(F("## Client NTP (Time) START .... OK"));
		 //char NTP_server[] = "europe.pool.ntp.org";   // 46.243.26.34
         NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
         IPAddress timeServer;     // NTP server address
         timeClient.begin();
         delay(100);
         timeClient.update();
         OK();  Serial.print(F("   Time : ")); Serial.println(timeClient.getFormattedTime() );                      // GET Heure : 12:22:01
         OK();  Serial.print(F("   Date : ")); Serial.println(timeClient.getFormattedDate() );                      // Get Date : 2020-03-21
         //timeClient.getFormattedDate().toCharArray(conf.timeReboot, 25);                                              // taille suffisante pour "YYYY-MM-DDTHH:MM:SSZ" + '\0'        
         strcpy(conf.timeReboot, timeClient.getFormattedDate().substring(0,10).c_str());
         strcat(conf.timeReboot, " ");
         strcat(conf.timeReboot, timeClient.getFormattedTime().c_str());                                                //"DD/MM/YYYY HH:MM" + '\0'
          
     }
     else 
	 {
		 FAILED();   Serial.println(F("## WAN ERROR !!! NTP OFF !")); 
	 }	 
 
  //Serial.println();                                                                                                      // Connexion Ethernet OK
  //Netstat(nullptr);
  //Serial.println();   
} 
