//com 10
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <TimeLib.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <FS.h>
#include <Wire.h>

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define BlinkingRedLed             12          //it's D6  Led Light

char auth[] = "XXXXXXXXXXXXXXXXXXXX";
const long utcOffsetInSeconds = 3600;
String SPIFFSTempPath="/Clock.txt";

// Your WiFi credentials.
// Set password to "" for open networks.

char ssid[] = "Magna";
char pass[] = "SuperOnda";

long rssi;

BlynkTimer timer;

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "gr.pool.ntp.org");

WidgetTerminal Terminal(V12);
   

/*-----( Declare Variables )-----*/

boolean ActivateEnable    = true;
boolean CommandsTriggered = false;

int    V0ButtonBlynk;
int    V10ButtonBlynk;                  //This is the user time Selection in milliseconds
int    CurrentTimeInMilliSeconds;       //Current Time in Milliseconds

int V1Led=1;
int V2Led=1;
int V3Led=1;
int V4Led=1;
int V5Led=1;
int V6Led=1;
int V7Led=1;
int V8Led=1;
int V9Led=1;

int CurrentDay = 0;
int WeekDay    = 0;

String CommandString="";
String RFCalibrate="";
String LiveTime;
char *SplitCommands[20]; // an array of pointers to the pieces of the above array after strtok()


/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
void clockDisplay()
{
  int Hours;

  
  timeClient.update();
  /*Serial.print(timeClient.getHours());
  Serial.print(":");
  Serial.print(timeClient.getMinutes());
  Serial.print(":");
  Serial.println(timeClient.getSeconds());*/
  //Serial.println(timeClient.getFormattedTime());
  
  unsigned long epochTime = timeClient.getEpochTime();
  //struct tm *ptm = gmtime ((time_t *)&epochTime);

  time_t rawtime = epochTime;
  struct tm *ptm = gmtime(&rawtime);
  
  CurrentDay = ptm->tm_mday;
  
  //WeekDay=timeClient.getDay();
  Hours=timeClient.getHours()+3;  //from 27/4 we should set +3 //  from 30/11 we should set +2
  if (Hours==24)
  {
     Hours=0;
  } 
  CurrentTimeInMilliSeconds=Hours*3600+timeClient.getMinutes()*60+timeClient.getSeconds();
  /*Serial.print("Current time : ");
  Serial.print(Hours);
  Serial.print(":");
  Serial.print(timeClient.getMinutes());
  Serial.print(":");
  Serial.print(timeClient.getSeconds());
  Serial.print("   ");*/
  
  //Serial.println(CurrentTimeInMilliSeconds);
  LiveTime=String(Hours)+String(":")+String(timeClient.getMinutes())+String(":")+String(timeClient.getSeconds());
  Blynk.virtualWrite(V11,LiveTime);   
}
/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/

void CommandToArduino()
{
  String Temp;
 
  if ((CommandsTriggered==0) && (CurrentTimeInMilliSeconds>=V10ButtonBlynk))
  {
    Serial.println("CurrentTimeInMilliSeconds : " + String(CurrentTimeInMilliSeconds));
    Serial.println("User Time Selection : " + String(V10ButtonBlynk));
    delay(100);
    Blynk.virtualWrite(V12,"CurrentTimeInMilliSeconds : " + String(CurrentTimeInMilliSeconds));
    Blynk.virtualWrite(V12,"User Time Selection : " + String(V10ButtonBlynk));
    delay(100);
    
    Blynk.virtualWrite(V12,"Entering Auto Shutdown in 15 Seconds.");
    delay(15000);
    if( (CurrentDay % 2) == 0) 
    { 
      CommandString="OFF,2,6,8";
      CommandsTriggered=1;
      Serial.println(CommandString);
      SplitCommandsUpdateLedVariables();
      Blynk.virtualWrite(V12,"Auto Commands : " + CommandString);
      V2Led=0;
      V6Led=0;
      V8Led=0;
      LedStatus();
    }
    else
    {
      CommandString="OFF,3,7,9";
      CommandsTriggered=1; 
      Serial.println(CommandString); 
      SplitCommandsUpdateLedVariables(); 
      Blynk.virtualWrite(V12,"Auto Commands : " + CommandString); 
      V3Led=0;
      V7Led=0;
      V9Led=0;  
      LedStatus();   
    }
  
    /*Allways off every night*/
    CommandString="OFF,1,4,5";
    CommandsTriggered=1; 
    Serial.println(CommandString); 
    SplitCommandsUpdateLedVariables(); 
    Blynk.virtualWrite(V12,"Auto Commands : " + CommandString);
    V1Led=0;
    V4Led=0;
    V5Led=0;  
    LedStatus();
  
  } 
}

/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
void SplitCommandsUpdateLedVariables()
{
   int TempSelection=0;
   
   char array[20] = "";
   CommandString.toCharArray(array, 20);
   char *ptr = NULL;
   byte index = 0;
   ptr = strtok(array, ",");  // delimiter
   while (ptr != NULL)
   {
      SplitCommands[index] = ptr;
      index++;
      ptr = strtok(NULL, ",");
   }
   for (int n = 0; n < index; n++)
   {
      Serial.print(n);
      Serial.print("<->");
      Serial.println(SplitCommands[n]);
   }


   if (String(SplitCommands[0])=="OFF")
   {
        for (int n = 1; n < index; n++)
       {
           TempSelection=String(SplitCommands[n]).toInt();
          switch (TempSelection) 
          {
            case 1:
              if (V1Led==1) {V1Led=0; Wire.beginTransmission(8);Wire.write("A"); delay(100);Wire.endTransmission();}
              break;
            case 2:
              if (V2Led==1) {V2Led=0; Wire.beginTransmission(8);Wire.write("B"); delay(100);Wire.endTransmission();}
              break;
            case 3:
              if (V3Led==1) {V3Led=0; Wire.beginTransmission(8);Wire.write("C"); delay(100);Wire.endTransmission();}
              break;
            case 4:
              if (V4Led==1) {V4Led=0; Wire.beginTransmission(8);Wire.write("D"); delay(100);Wire.endTransmission();}
              break;
            case 5:
              if (V5Led==1) {V5Led=0; Wire.beginTransmission(8);Wire.write("E"); delay(100);Wire.endTransmission();}
              break;
            case 6:
              if (V6Led==1) {V6Led=0; Wire.beginTransmission(8);Wire.write("F"); delay(100);Wire.endTransmission();}
              break;
            case 7:
              if (V7Led==1) {V7Led=0; Wire.beginTransmission(8);Wire.write("G"); delay(100);Wire.endTransmission();}
              break;              
            case 8:
              if (V8Led==1) {V8Led=0; Wire.beginTransmission(8);Wire.write("H"); delay(100);Wire.endTransmission();}
              break; 
            case 9:
              if (V9Led==1) {V9Led=0; Wire.beginTransmission(8);Wire.write("I"); delay(100);Wire.endTransmission();}
              break; 
            default:
            //
            break;
            }
       }
       LedStatus();
   }



   if (String(SplitCommands[0])=="ON")
   {
       for (int n = 1; n < index; n++)
       {
          TempSelection=String(SplitCommands[n]).toInt();
          switch (TempSelection) 
          {
            
            case 1:
              if (V1Led==0) {V1Led=1; Wire.beginTransmission(8);Wire.write("A"); delay(100); Wire.endTransmission(); }
                break;
            case 2:
              if (V2Led==0) {V2Led=1; Wire.beginTransmission(8);Wire.write("B"); delay(100); Wire.endTransmission();}
                break;
            case 3:
              if (V3Led==0) {V3Led=1; Wire.beginTransmission(8);Wire.write("C"); delay(100); Wire.endTransmission();}
                break;
            case 4:
              if (V4Led==0) {V4Led=1; Wire.beginTransmission(8);Wire.write("D"); delay(100); Wire.endTransmission();}
                break;
            case 5:
              if (V5Led==0) {V5Led=1; Wire.beginTransmission(8);Wire.write("E"); delay(100); Wire.endTransmission();}
              break;
            case 6:
              if (V6Led==0) {V6Led=1; Wire.beginTransmission(8);Wire.write("F"); delay(100); Wire.endTransmission();}
              break;
            case 7:
              if (V7Led==0) {V7Led=1; Wire.beginTransmission(8);Wire.write("G"); delay(100); Wire.endTransmission();}
              break;
            case 8:
              if (V8Led==0) {V8Led=1; Wire.beginTransmission(8);Wire.write("H"); delay(100); Wire.endTransmission();} 
              break; 
            case 9:
              if (V9Led==0) {V9Led=1; Wire.beginTransmission(8);Wire.write("I"); delay(100); Wire.endTransmission();}
              break;        
             default:
             //
             break;
          }
       }
       LedStatus();
   }
}
/*------------------------------------------------------------------------------------------------------------*/
void LedStatus()
{
  Serial.println("Led Status Update"); 
  if (V1Led==1) { Blynk.virtualWrite(V1,255); Serial.println("Led No 1 ON"); } else { Blynk.virtualWrite(V1,0);Serial.println("Led No 1 OFF"); }
  if (V2Led==1) { Blynk.virtualWrite(V2,255); Serial.println("Led No 2 ON"); } else { Blynk.virtualWrite(V2,0);Serial.println("Led No 2 OFF"); }
  if (V3Led==1) { Blynk.virtualWrite(V3,255); Serial.println("Led No 3 ON"); } else { Blynk.virtualWrite(V3,0);Serial.println("Led No 3 OFF"); }
  if (V4Led==1) { Blynk.virtualWrite(V4,255); Serial.println("Led No 4 ON"); } else { Blynk.virtualWrite(V4,0);Serial.println("Led No 4 OFF"); }
  if (V5Led==1) { Blynk.virtualWrite(V5,255); Serial.println("Led No 5 ON"); } else { Blynk.virtualWrite(V5,0);Serial.println("Led No 5 OFF"); }
  if (V6Led==1) { Blynk.virtualWrite(V6,255); Serial.println("Led No 6 ON"); } else { Blynk.virtualWrite(V6,0);Serial.println("Led No 6 OFF"); }
  if (V7Led==1) { Blynk.virtualWrite(V7,255); Serial.println("Led No 7 ON"); } else { Blynk.virtualWrite(V7,0);Serial.println("Led No 7 OFF"); }
  if (V8Led==1) { Blynk.virtualWrite(V8,255); Serial.println("Led No 8 ON"); } else { Blynk.virtualWrite(V8,0);Serial.println("Led No 8 OFF"); }  
  if (V9Led==1) { Blynk.virtualWrite(V9,255); Serial.println("Led No 9 ON"); } else { Blynk.virtualWrite(V9,0);Serial.println("Led No 9 OFF"); }    
}
/*------------------------------------------------------------------------------------------------------------*/

void reconnectBlynk() {
  if (!Blynk.connected()) {
    Serial.println("Lost connection");
    if(Blynk.connect()) Serial.println("Reconnected");
    else Serial.println("Not reconnected");
  }
}
/*------------------------------------------------------------------------------------------------------------*/

BLYNK_WRITE(V10){
 V10ButtonBlynk = param.asInt(); 
 Serial.print("User Date Selection : ");
 Serial.println(V10ButtonBlynk);
 delay(100);
 Blynk.virtualWrite(V12,"User Date Selection : " + String(V10ButtonBlynk));
 delay(100);
 WriteSPIFFS();
 delay(100);
 CommandsTriggered=0;
 Blynk.virtualWrite(V12,"Auto Trigger Commands were reset.");
}
/*------------------------------------------------------------------------------------------------------------*/
BLYNK_WRITE(V12){
 CommandString = param.asString(); 
 SplitCommandsUpdateLedVariables();
 Serial.print("User Command from Terminal : ");
 Serial.println(CommandString);
}
/*------------------------------------------------------------------------------------------------------------*/
BLYNK_WRITE(V0){
 V0ButtonBlynk = param.asInt(); 
 if (V0ButtonBlynk==0)
   {
       Serial.println("Activate Lights OFF");  
       ActivateEnable=V0ButtonBlynk; 
       Blynk.virtualWrite(V12,"Activate Lights OFF");
   }   else 
       {
        Serial.println("Activate Lights ON");  
        ActivateEnable=V0ButtonBlynk;  
        Blynk.virtualWrite(V12,"Activate Lights ON");
        CommandsTriggered=0;
        Blynk.virtualWrite(V12,"Auto Trigger Commands were reset.");
   }
}

/*------------------------------------------------------------------------------------------------------------*/
/*BLYNK_WRITE(V4){
 V4ButtonBlynk = param.asInt(); 
 if (V4ButtonBlynk)
   {
       Serial.println("Pressed V4 From Mobile - OFF");  
       digitalWrite(Relay, HIGH); 
   }   else 
       {
        Serial.println("Pressed V4 From Mobile - ON");  
        digitalWrite(Relay, LOW); 
   }
}*/

/*------------------------------------------------------------------------------------------------------------*/
void ReadSPIFFS()
{
 char inputString [100];
 char inputChar;
 int stringIndex = 0; // String stringIndexing int;

  Serial.println("Starting Reading SPIFFS module.");
  Blynk.virtualWrite(V12,"Starting Reading SPIFFS module.");

  if(!SPIFFS.begin())
  {
     Serial.println("An Error has occurred while mounting SPIFFS");
     Blynk.virtualWrite(V12,"An Error has occurred while mounting SPIFFS");
     return;
  }

  if (SPIFFS.exists(SPIFFSTempPath))
  {
        File ReadFile = SPIFFS.open(SPIFFSTempPath,"r");
        if(!ReadFile)
        {
            Serial.println("Failed to open file for reading");
            Blynk.virtualWrite(V12,"An Error has occurred while mounting SPIFFS");
            return;
        }
    


    while (ReadFile.available()) 
      { //execute while file is available
            char letter = ReadFile.read(); //read next character from file
            if (isDigit(letter))
            {
                inputString[stringIndex]=letter;
                stringIndex++;
                delay(300);
            }
      }

     Serial.print("File Content:"); 
     Serial.println(inputString);
     V10ButtonBlynk=atoi(inputString);
     Serial.print("User Date Selection : "); 
     Serial.println(String(V10ButtonBlynk));
     Blynk.virtualWrite(V12,"User Date Selection : " + String(V10ButtonBlynk));
     delay (500);
     ReadFile.close();
     delay(1000);
  }
  Serial.println("End Reading SPIFFS Module.");
  Blynk.virtualWrite(V12,"End Reading SPIFFS Module.");
}
/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
void WriteSPIFFS()
{
  Serial.println("Starting Writing SPIFFS module.");
  Blynk.virtualWrite(V12,"Starting Writing SPIFFS module.");

  if(!SPIFFS.begin())
  {
     Serial.println("An Error has occurred while mounting SPIFFS.");
     Blynk.virtualWrite(V12,"An Error has occurred while mounting SPIFFS.");
     return;
  }

  File WriteFile = SPIFFS.open(SPIFFSTempPath,"w");
  if(!WriteFile){
     Serial.println("There was an error opening the file for writing.");
     Blynk.virtualWrite(V12,"There was an error opening the file for writing.");
     return;
  }
      
  if(WriteFile.print(String(V10ButtonBlynk))){
     Serial.println("File was written");
     delay(100);
     Blynk.virtualWrite(V12,"File was written");
     delay(100);
  } else {
     Serial.println("File write failed");
     delay(100);
     Blynk.virtualWrite(V12,"File write failed");
     delay(100);
  }
  delay(1000);
  
  WriteFile.close();

  Serial.println("End Writing SPIFFS Module.");
  Blynk.virtualWrite(V12,"End Writing SPIFFS Module.");
}
/*------------------------------------------------------------------------------------------------------------*/

void setup()
{
  // Debug console
  Serial.begin(9600);

  Wire.begin(05,04); /* join i2c bus with SDA=D1 and SCL=D2 of NodeMCU */

  pinMode(BlinkingRedLed, OUTPUT);

  ESP.wdtDisable();
  delay(10);
  Serial.print("Trying to Connect to Wifi : ");
  Serial.println(ssid);  
  WiFi.begin(ssid, pass);

  

  while (WiFi.status() != WL_CONNECTED)
  {
     Serial.println("### No Connection ###");
     delay(1000);
   }

  delay(1000);

  Serial.println("WiFi connected");
  Blynk.begin(auth, ssid, pass);
  ESP.wdtEnable(WDTO_8S);
  delay(1000);

  Terminal.clear();
  Blynk.virtualWrite(V12,"-----------------------");
  Blynk.virtualWrite(V12,"WiFi connected to AP : "+ String(ssid)); 
  delay(1000);

  rssi = WiFi.RSSI();
  Serial.print("Wifi Signal : ");
  Serial.println(rssi);
  Blynk.virtualWrite(V12,"Wifi Signal :"+String(rssi)); 
  delay(1000);
  
  clockDisplay();
  delay(1000);

  ReadSPIFFS();
  delay(1000);
   
  /*V10ButtonBlynk=900;         //i am setting the hour as 00:15 to start closing lights*/
  Blynk.virtualWrite(V10,V10ButtonBlynk);

  timeClient.begin();
 
  Serial.println("Finish Setup.");
  delay(1000);

  Blynk.virtualWrite(V0,1);

  V1Led=1;
  V2Led=1;
  V3Led=1;
  V4Led=1;
  V5Led=1;
  V6Led=1;
  V7Led=1;
  V8Led=1;
  V9Led=1;

  LedStatus();
 
  String Temp = "Current Day : " + String(CurrentDay);
  Blynk.virtualWrite(V12,Temp );
  
  Temp = "Live Time : " + String(LiveTime);
  Blynk.virtualWrite(V12,Temp );
  Blynk.virtualWrite(V12,"Setup Finished !" );
}
/*------------------------------------------------------------------------------------------------------------*/
void loop()
{
  timer.run();   
  if(Blynk.connected())
  {
    Blynk.run();  
    clockDisplay();
    delay(1000);
    if (ActivateEnable==1)
    {
      CommandToArduino();
    }
 } else 
 
 {
  Serial.println("Non Connection....Forcing Restart");
  delay(2000);
  ESP.restart();
 }
 
}
