// Learn about the ESP32 WiFi simulation in
// https://docs.wokwi.com/guides/esp32-wifi

#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 20, 4);
RTC_DS1307 rtc;

#define NTP_SERVER     "pool.ntp.org"
#define UTC_OFFSET     0
#define UTC_OFFSET_DST 0

DateTime now;
DateTime shutTime;
DateTime openTime;
DateTime lastResync;
int timeSinceLastResync;


TaskHandle_t TaskHandle_0;
TaskHandle_t Task2;
int btnState;
int btnState2;

enum doorstate
{
  OPEN,
  CLOSED,
  CALIBRATING,
  BROKEN,
  UP,
  DOWN,
};
doorstate dstate;


void spinner() {
  static int8_t counter = 0;
  const char* glyphs = "\xa1\xa5\xdb";
  LCD.setCursor(15, 1);
  LCD.print(glyphs[counter++]);
  if (counter == strlen(glyphs)) {
    counter = 0;
  }
}


void printLocalTime() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    LCD.setCursor(0, 1);
    LCD.println("Connection Err");
    return;
  }

  LCD.setCursor(8, 0);
  LCD.println(&timeinfo, "%H:%M:%S");

  LCD.setCursor(0, 1);
  LCD.println(&timeinfo, "%d/%m/%Y   %Z");
}

void setup() {
  Serial.begin(115200);

  LCD.init();
  LCD.backlight();
  LCD.setCursor(0, 0);
  LCD.print("Connecting to ");
  LCD.setCursor(0, 1);
  LCD.print("WiFi ");

    if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    abort();
  }


  WiFi.begin("Wokwi-GUEST", "", 6);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    spinner();
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  LCD.clear();
  LCD.setCursor(0, 0);
  LCD.println("Online");
  LCD.setCursor(0, 1);
  LCD.println("Updating time...");

  configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
  //uses UTP time server to sync time
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Connection Err");
    abort();
  }

  String AMorPM;
  if (timeinfo.tm_hour > 12) {
    AMorPM = "PM";
  } else {
    AMorPM = "AM";
  }

  //adjusts dateTime so time is always synced up properly
  rtc.adjust(DateTime(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec));
  now = rtc.now();
  shutTime = DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute() + 1, 0);
  lastResync = rtc.now();
  LCD.clear();

      xTaskCreate(
      dostuff, // Function to implement the task 
      "otherThings", // Name of the task 
      10000,  // Stack size in words 
      NULL,  // Task input parameter 
      1,  // Priority of the task 
      &TaskHandle_0  // Task handle. 
      );
}

void dostuff(void * pvParameters)
{
 Serial.print("time: ");
  Serial.println(xPortGetCoreID());
  
  while(true){

  if(now.hour() >= shutTime.hour() && now.minute() >= shutTime.minute())
  {
    dstate = CLOSED;
  }

  else if(now.hour() >= openTime.hour() && now.minute() >= openTime.minute())
  {
   dstate = OPEN;
  }

  timeSinceLastResync = now.minute() - lastResync.minute();
  Serial.println(timeSinceLastResync);

  if(timeSinceLastResync == 2)
  {
    resyncClocks();
    dstate = CALIBRATING;
  }

  /*
  Serial.print("Now valid ");
  Serial.println(now.isValid());
  Serial.print("shuttime valid ");
  Serial.println(shutTime.isValid());
  Serial.print("hours match ");
  Serial.println(now.hour() >= shutTime.hour());
  Serial.print("Minutes match ");
  Serial.println( now.minute() >= shutTime.minute());
  Serial.println(shutTime.minute());
  Serial.println(now.minute());
  */

  delay(500);
  }
}

void resyncClocks()
{
  configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
  //uses UTP time server to sync time
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Connection Err");
    abort();
  }

  String AMorPM;
  if (timeinfo.tm_hour > 12) {
    AMorPM = "PM";
  } else {
    AMorPM = "AM";
  }

  //adjusts dateTime so time is always synced up properly
  rtc.adjust(DateTime(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec));
  lastResync = rtc.now();
} 


void loop() {
  LCD.setCursor(0,3);
  switch(dstate)
  {
    case OPEN:
    
    LCD.print("Door Open");
    break;

    case CLOSED:
    
    LCD.print("Door closed");
    break;
  
    case CALIBRATING:
    LCD.print("Time resyncronising");
  }

now = rtc.now();
LCD.setCursor(0, 0);
if(now.hour() < 10){
  LCD.print('0');
  }
  LCD.print(now.hour(), DEC);
  LCD.print(':');
  if(now.minute() < 10){
  LCD.print('0');
  }
  LCD.print(now.minute(), DEC);
  LCD.print(':');
    if(now.second() < 10){
  LCD.print('0');
  }
  LCD.print(now.second(), DEC);
  /*
  LCD.print(" ");
  LCD.print(now.hour() % shutTime.hour(), DEC);
  LCD.print(':');
  LCD.print(now.minute() % shutTime.minute(), DEC);
  */
  LCD.setCursor(0, 1);
  LCD.print(shutTime.hour(), DEC);
  LCD.print(':');
  if(shutTime.minute() < 10){
  LCD.print('0');
  }
  LCD.print(shutTime.minute(), DEC);
  LCD.print(':');
  LCD.print(shutTime.second(), DEC);

  LCD.setCursor(0, 2);
  LCD.print(openTime.hour(), DEC);
  LCD.print(':');
  LCD.print(openTime.minute(), DEC);
  LCD.print(':');
  LCD.print(openTime.second(), DEC);

  delay(10);
}
GND5VSDASCLSQWRTCDS1307+