
#define TINY_GSM_MODEM_ESP8266
#include <ArduinoJson.h>
#define SerialMon Serial
#define SerialAT Serial1
#include <Adafruit_CircuitPlayground.h>
#define BLYNK_PRINT SerialUSB
#define BLYNK_DEBUG SerialUSB
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

// Used for the color later on
struct Color {
  uint32_t hex;
};

Color myColor;


#if !defined(TINY_GSM_RX_BUFFER)

#define TINY_GSM_RX_BUFFER 1500
#endif

#define TINY_GSM_DEBUG SerialMon
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200

// Your WiFi connection credentials, if applicable
char auth[] = "hMy6PVOhYOxEUZe97U3H5CYteuEJlw7t";
const char wifiSSID[] = "Apartment";
const char wifiPass[] = "0524387839";

// Server details
const char server[] = "worldtimeapi.org";
// The city can be changed. Currently set to Jerusalem Time Zone
const char resource[] = "/api/timezone/Asia/Jerusalem";


#define EspSerial Serial1
#define ESP8266_BAUD 115200

ESP8266 wifi(&EspSerial);

long last_sent = 0;




#include <TinyGsmClient.h>

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif

TinyGsmClient client(modem);
const int port = 80;

#include <ESP8266_Lib.h>
#include <Adafruit_CircuitPlayground.h>


int alarmhour = -2;
int alarmminute = -2;


#define EspSerial Serial1
#define ESP8266_BAUD 115200





void setup() {
  CircuitPlayground.begin();
  SerialUSB.begin(9600);
  

  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, wifiSSID, wifiPass);
  

  CircuitPlayground.begin();
  SerialMon.begin(115200);
  delay(1000);

  SerialAT.begin(115200);
  SerialMon.println("Initializing modem...");
  modem.restart();
  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);

}

void loop() {
  
  
  
  
  
  
  
  int hour = -1;
  int minute = -1;
  int second = -1;
// waits until both the alarm minute and alarm hour are set on Blynk
  while(alarmhour < 0 || alarmminute < 0)
  {
    Blynk.run();

  if((millis() - last_sent) >  10000) {
    Blynk.virtualWrite(V2, random(0,1000));
    last_sent = millis();
  }
  }
  
  //just keeps ticking until the alarm hour is set
  while(hour !=alarmhour || minute != alarmminute){
    //makes sure that the program runs as close to the full second as possible 
    delay(60000 - (second*1000));

    
  
  SerialMon.print(F("Setting SSID/password..."));
  
  if (!modem.networkConnect(wifiSSID, wifiPass))
  {
    SerialMon.println(" fail");
    delay(5000);
    return;
  }
  SerialMon.println(" success");
  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork())
  {
    SerialMon.println(" fail");
    delay(5000);
    return;
  }
  SerialMon.println(" success");

  if (modem.isNetworkConnected())
  {
    SerialMon.println("Network connected");
  }

  SerialMon.print("Connecting to ");
  SerialMon.println(server);
  if (!client.connect(server, port))
  {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");

  
  SerialMon.println("Performing HTTP GET request...");
  client.print(String("GET ") + resource + " HTTP/1.1\r\n");
  client.print(String("Host: ") + server + "\r\n");
  client.print("Connection: close\r\n\r\n");
  client.println();

  uint32_t timeout = millis();
  bool responseStarted = false;
  String jsonStr;

  while (client.connected() && millis() - timeout < 10000L)
  {
    
    while (client.available())
    {
      char c = client.read();
      if (c == '{')
      {
        responseStarted = true;
      }
      if (responseStarted)
      {
        // Build the JSON document
        jsonStr += c;
      }
    }
    timeout = millis();
  }
  
  //prints the information from the time api 
  SerialMon.println(jsonStr);
  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, jsonStr);

  if (error)
  {
    SerialMon.print("Error parsing JSON: ");
    SerialMon.println(error.c_str());
    return;
  }

  // Extract the hour and minute
  String datetime = doc["datetime"];
  hour = datetime.substring(11, 13).toInt();
  minute = datetime.substring(14, 16).toInt();
  second = datetime.substring(17, 19).toInt();

  // Prints the extracted data and the alarm data
  SerialMon.print("AlarmHour: ");
  SerialMon.println(alarmhour);
  SerialMon.print("AlarmMinute: ");
  SerialMon.println(alarmminute);
  SerialMon.print("Hour: ");
  SerialMon.println(hour);
  SerialMon.print("Minute: ");
  SerialMon.println(minute);
  SerialMon.print("Second: ");
  SerialMon.println(second);
 }
 
 myColor.hex = 0xFF0000;

 while (!CircuitPlayground.leftButton() && !CircuitPlayground.rightButton()) {
    // Flash all the LEDs
    for (int i = 0; i < 10; i++) {
      CircuitPlayground.setPixelColor(i, myColor.hex); // Set color to red
    }
    SerialMon.println("Alarm!!");
    CircuitPlayground.playTone(1000, 100);
    
    delay(500);
    CircuitPlayground.clearPixels();
    
    delay(500);
  }

  // Do nothing forevermore
  while (true)
  {
    delay(1000);
  }
}
BLYNK_WRITE(V0) {
  alarmhour = param.asInt(); // assigning incoming value from pin V0 to a variable
  Serial.println("Alarm Hour set to");
  Serial.println(alarmhour);
  
}

BLYNK_WRITE(V1) {
  alarmminute = param.asInt(); // assigning incoming value from pin V1 to a variable
  Serial.println("Alarm Minute set to");
  Serial.println(alarmminute);
  
}
