#include <EEPROM.h>
#include "credentials.h"


int           adr_par=3;                  //Ważne!!! adres początku parametrów w eeprom (większe od 0)
String        roboS2;                     //robocza globalna
byte          prz_setup=0;                //wsk. nacisnięcia przycisku ustawień
byte          sesja=0;                    //wskaźnik sesji ustawiania parametrów
bool          wifi_conn=false;            //wskaznik polaczenia do wifi
char          par_n_AP[20];                
char          par_h_AP[20];
byte          timeout=0;                    //licznik nieudanego łączenia do AP
bool ustawianie = false;
IPAddress     klientIP(0,0,0,0);            //tu będą wstawione wartości IP statycznego
IPAddress     gateway(0,0,0,0);             //tu będą wstawione wartości IP bramy
IPAddress     subnet(255,255,255,0);        //maska (niezmienna)


typedef struct {                        //struktura ustawionych parametrów:
                String ap_ssid;         //SSID AP istniejącej sieci, 20 zn, (nazwa_ssid_sieci)
                String ap_haslo;        //haslo AP istniejącej sieci, 20 zn, (haslo_dostepu)
                String ip_klient;       //static IP klienta ustawień, 15 zn,(np. 192.168.0.140)
                String ip_brama;        //brama IP w istniejącej sieci, 15 zn, (np. 192.168.0.1)
                String wb_ssid;         //SSID WebServera, 20 zn, (np. ESP32-CAM_Wartownik)
                String wb_haslo;        //hasło do WebServera, 20 zn, (np. administrator)
                String n_nadaw;         //nazwa skrzynki nadawczej, 20 zn., 
                String h_nadaw;         //hasło skrzynki nadawczej (aplikacji), 20 zn.,
                String n_smtp;          //nazwa serwera smtp, 20 zn., 
                String nr_port;         //nr portu serwera smtp, 3 zn., 
                String n_docel;         //nazwa docelowej skrzynki e-mail, 20 zn.,
                String temat;           //temat wiadomosci e-mail, 20 zn.,
                String min_czas;        //minimalny czas między wysyłanie e-maili, 2 zn.
                String godzina;         //godzina wysłania ostatniego maila
                String minuta;          //minuta wysłania ostatniego maila
              } PARA;

PARA parametry={"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""};               
 

/************************************************
 * ustawienie parametrów na wartości defaultowe
 ************************************************ */
void ustawParametryDefault()
{
  Serial.println("Ustawienie parametrów defaultowych");
  parametry.ap_ssid= mySSID;                  //SSID AP istniejącej sieci, 20 zn,
  parametry.ap_haslo= myPASSWORD;             //haslo AP istniejącej sieci, 20 zn,
  parametry.ip_klient= DefaultIP;             //static IP układu w istniejącej sieci, 15 zn,
  parametry.ip_brama= GatewayIP;              //gataway IP w istniejącej sieci, 15 zn,
  parametry.wb_ssid= WbSsid;                  //SSID WebServera ustawień, 20 zn,
  parametry.wb_haslo= WbHaslo;                //hasło do WebServera ustawień, 20 zn,
  parametry.n_nadaw= emailSenderAccount;      //nazwa skrzynki nadawczej, 20 zn.
  parametry.h_nadaw= emailSenderPassword;     //hasło skrzynki nadawczej (aplikacji), 20 zn,
  parametry.n_smtp= smtpServer;               //nazwa serwera smtp, 20 zn,
  parametry.nr_port= smtpServerPort;          //nr portu serwera smtp, 3 zn,
  parametry.n_docel= emailRecipient;          //nazwa skrzynki docelowej, 20 zn,
  parametry.temat= emailSubject;              //temat wiadomosci e-mail, 20 zn.,
  parametry.min_czas= 5;                      //minimalny czas między wysyłaniem e-maili w minutach
}


/************************************************************************************************
 * zapis stringu znaki do eeprom o adresie początku adr, dopełnienie spacjami do długości ilosc
 ************************************************************************************************ */
void writeEEPROM(String znaki, int adr, int ilosc)
{
  String znak;
  int dl_str = znaki.length();

  for (int i = 0; i < dl_str; i++)                  //zapis do eeprom znaków stringu
  {
    znak=znaki[i];
    if (znak=="+")
      EEPROM.write(adr+i, byte(32));                //zamiana + na spację
    else
      EEPROM.write(adr+i, byte(znaki[i]));
  }

  if (dl_str<ilosc)                                 //dopelnienie spacjami
  {
    for (int i=0; i<(ilosc-dl_str); i++)
    {
      EEPROM.write(adr+dl_str+i, byte(32));
    }
  }
}

/***************************************************************
 * odczyt stringu z eeprom do roboS2 bez spacji z prawej strony
 *************************************************************** */
void readEEPROM(int adr, int ilosc)
{
  byte il_sp=0;
  
  roboS2="";
  for (int i = 0; i < ilosc; i++)
  {
    if (EEPROM.read(adr+i) != 32)                      //spacja = 32
    {
      if (il_sp>0)
      {
        for (byte i2=0; i2<il_sp; i2++)
        {
          roboS2 += " ";
        }
        il_sp = 0;
      }
      roboS2 += char(EEPROM.read(adr+i));
    }
    else
      il_sp++;
  }
}

/*****************************************************
 * wpisanie do tablicy parametry[] wartości z eeprom
 ***************************************************** */
void eepromReadParametry()
{
  readEEPROM(adr_par+1, 20);                //odczyt nazwy SSID AccessPoint do roboS2
  parametry.ap_ssid=roboS2;      

  readEEPROM(adr_par+21, 20);               //odczyt hasła do AccessPointa do roboS2
  parametry.ap_haslo=roboS2;       

  readEEPROM(adr_par+41, 15);               //odczyt static IP klienta Wartownika do roboS2
  parametry.ip_klient=roboS2;      
  
  readEEPROM(adr_par+56, 15);               //odczyt gateway IP (brama) do roboS2
  parametry.ip_brama=roboS2;      

  readEEPROM(adr_par+71, 20);               //odczyt SSID klienta WebServera do roboS2
  parametry.wb_ssid=roboS2;      
  
  readEEPROM(adr_par+91, 20);               //odczyt WebServer password do roboS2
  parametry.wb_haslo=roboS2;      

  readEEPROM(adr_par+111, 20);              //odczyt nazwy skrzynki nadawczej do roboS2
  parametry.n_nadaw=roboS2;      

  readEEPROM(adr_par+131, 20);              //odczyt hasła skrzynki nadawczej do roboS2
  parametry.h_nadaw=roboS2;      

  readEEPROM(adr_par+151, 20);              //odczyt nazwy serwera smtp do roboS2
  parametry.n_smtp=roboS2;      

  readEEPROM(adr_par+171, 3);               //odczyt nr portu serwera smtp do roboS2
  parametry.nr_port=roboS2;      

  readEEPROM(adr_par+174, 20);              //odczyt nazwy skrzynki docelowej do roboS2
  parametry.n_docel=roboS2;      

  readEEPROM(adr_par+194, 20);              //odczyt tematu wiadomosci e-mail do roboS2
  parametry.temat=roboS2;      

  readEEPROM(adr_par+214, 2);              //minimalny czas między e-mailami do roboS2
  parametry.min_czas=roboS2;      

  readEEPROM(adr_par+216, 2);              //gopdzina wysłania ostatniego e-maila do roboS2
  parametry.godzina=roboS2;      

  readEEPROM(adr_par+218, 2);              //minuta wysłania ostatniego e-maila do roboS2
  parametry.minuta=roboS2;      
}

/******************************************************************
 * jeżeli zawartosć w eeprom jest różna od zawartości tablicy
 * parametry[], wpisanie do eeprom wartości z tablicy parametry[] 
 * Oszczędzanie ilości zapisów do eeprom.
 ****************************************************************** */ 
void eepromWriteParametry()
{
  byte zapis=0;
  
  readEEPROM(adr_par+1, 20);                            //odczyt do roboS2
  if (roboS2 != parametry.ap_ssid)
  {
    writeEEPROM(parametry.ap_ssid, adr_par+1, 20);      //zapis nazwy SSID AP
    zapis=1;
  }

  readEEPROM(adr_par+21, 20);                           //odczyt do roboS2
  if (roboS2 != parametry.ap_haslo)
  {
    writeEEPROM(parametry.ap_haslo, adr_par+21, 20);    //zapis hasła do AP
    zapis=1;
  }
  
  readEEPROM(adr_par+41, 15);                           //odczyt do roboS2
  if (roboS2 != parametry.ip_klient)
  {
    writeEEPROM(parametry.ip_klient, adr_par+41, 15);   //zapis adres IP klienta Wartownika
    zapis=1;
  }

  readEEPROM(adr_par+56, 15);                           //odczyt do roboS2
  if (roboS2 != parametry.ip_brama)
  {
    writeEEPROM(parametry.ip_brama, adr_par+56, 15);    //zapis adresu IP bramy
    zapis=1;
  }

  readEEPROM(adr_par+71, 20);                           //odczyt do roboS2
  if (roboS2 != parametry.wb_ssid)
  {
    writeEEPROM(parametry.wb_ssid, adr_par+71, 20);     //zapis nazwy SSID WebServera
    zapis=1;
  }

  readEEPROM(adr_par+91, 20);                           //odczyt do roboS2
  if (roboS2 != parametry.wb_haslo)
  {
    writeEEPROM(parametry.wb_haslo, adr_par+91, 20);    //zapis WebServer password
    zapis=1;
  }

  readEEPROM(adr_par+111, 20);                           //odczyt do roboS2
  if (roboS2 != parametry.n_nadaw)
  {
    writeEEPROM(parametry.n_nadaw, adr_par+111, 20);    //zapis nazwy skrzynki nadawczej
    zapis=1;
  }

  readEEPROM(adr_par+131, 20);                          //odczyt do roboS2
  if (roboS2 != parametry.h_nadaw)
  {
    writeEEPROM(parametry.h_nadaw, adr_par+131, 20);    //zapis hasła skrzynki nadawczej (aplikacji)
    zapis=1;
  }

  readEEPROM(adr_par+151, 20);                          //odczyt do roboS2
  if (roboS2 != parametry.n_smtp)
  {
    writeEEPROM(parametry.n_smtp, adr_par+151, 20);    //zapis nazwy serwera smtp
    zapis=1;
  }

  readEEPROM(adr_par+171, 3);                           //odczyt do roboS2
  if (roboS2 != parametry.nr_port)
  {
    writeEEPROM(parametry.nr_port, adr_par+171, 3);    //zapis nr portu serwera smtp
    zapis=1;
  }

  readEEPROM(adr_par+174, 20);                          //odczyt do roboS2
  if (roboS2 != parametry.n_docel)
  {
    writeEEPROM(parametry.n_docel, adr_par+174, 20);    //zapis nazwy skrzynki docelowej
    zapis=1;
  }

  readEEPROM(adr_par+194, 20);                          //odczyt do roboS2
  if (roboS2 != parametry.temat)
  {
    writeEEPROM(parametry.temat, adr_par+194, 20);     //zapis tematu wiadomosci e-mail
    zapis=1;
  }

  readEEPROM(adr_par+214, 2);                          //odczyt do roboS2
  if (roboS2 != parametry.min_czas)
  {
    writeEEPROM(parametry.min_czas, adr_par+214, 2);   //zapis minimalnego czasu między e-mailami
    zapis=1;
  }

  readEEPROM(adr_par+216, 2);                          //odczyt do roboS2
  if (roboS2 != parametry.godzina)
  {
    writeEEPROM(parametry.godzina, adr_par+216, 2);   //zapis godziny wysłania ostatniego e-maila
    zapis=1;
  }

  readEEPROM(adr_par+218, 2);                          //odczyt do roboS2
  if (roboS2 != parametry.minuta)
  {
    writeEEPROM(parametry.minuta, adr_par+218, 2);   //zapis minuty wysłania ostatniego e-maila
    zapis=1;
  }

  if (EEPROM.read(adr_par) != wsk_eeprom)               //odczyt wskaźnika - czy są ustawienia param. w eeprom
  {                                                     //nie ustawiono parametrów
    EEPROM.write(adr_par, wsk_eeprom);                  //zapis wskaźnika wykonanych ustawień
    zapis=1;
  }
  if (zapis>0)
    EEPROM.commit();
}

/**************************************************************************************************
 * zamiana adresu IP o strukturze xxx.xxx.xxx.xxx na cztery osobne stringi liczbowe (czlony(0..3])
 ************************************************************************************************** */
void  podzielIP(String adresIP, String czlony[4])
{
  int nr_zn=0;
  String czlon="";
  for (int nr_c=0; nr_c<4; nr_c++)
  {
    while ((nr_zn<adresIP.length()) and (String(adresIP[nr_zn])!="."))    //rozdzielone kropkami
    {
      czlon += adresIP[nr_zn];
      nr_zn++;
    }
    czlony[nr_c]=czlon;
    czlon="";
    nr_zn++;
  }
}


/********************************************************
 *   Łączenie do domowej sieci wi-fi dla SETUP
 ******************************************************** */  
void polacz_do_wifi()
{
  if (ustawianie)
  {
    WiFi.mode(WIFI_STA);                                          //polaczenie tylko z siecia wifi (dla SETUP)
    WiFi.config(klientIP, gateway, subnet);                       //konfiguracja stałego IP klienta dla domowej sieci wifi
  }
    WiFi.begin(par_n_AP, par_h_AP);                               //podłączenie do domowej sieci wifi (SSID z hasłem)
  
    Serial.printf("\nŁączenie do %s ", par_n_AP);
    while ((WiFi.status() != WL_CONNECTED) and (timeout<10))      //do 10 prób podłaczenia
    {
      delay(500);
      Serial.print(".");
      timeout++;
    }
    if (timeout<10)
    {
      Serial.println("\nWIFI podłączone.");
    }
}    
