#include <WiFi.h>
#include <PubSubClient.h>
#include "DHTesp.h"
#include <NTPClient.h>
#include <WiFiUdp.h>

#define BUZZER 12
const int DHT_PIN = 15;

WiFiClient espClient;
PubSubClient mqttClient(espClient);

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

DHTesp dhtSensor;
char tempAr[6];
bool isScheduledON = false;
unsigned long scheduledOnTime;

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

  setupWifi();
  setupMqtt();

  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
  timeClient.begin();
  timeClient.setTimeOffset(5.5 * 3600);

  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, LOW);
}

void loop() {
  if(!mqttClient.connected()){
    connectToBroker();
  }

  mqttClient.loop();

  updateTemperature();

  // Serial.print(tempAr);
  mqttClient.publish("MQTT-TEMP",tempAr);
  checkSchedule();
  delay(1000);
}

void setupWifi(){
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println("Wokwi-GUEST");
  WiFi.begin( "Wokwi-GUEST","");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.print("");
  Serial.print ("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void setupMqtt(){
  mqttClient.setServer("test.mosquitto.org",1883);
  mqttClient.setCallback(receiveCallback);
}

void connectToBroker(){
  while(!mqttClient.connected()){
    Serial.print("Attempting MQTT connection...");
    if(mqttClient.connect("ESP32-4654564645645")){
      Serial.println("connected");
      mqttClient.subscribe("MQTT-ON-OFF");
      mqttClient.subscribe("MQTT-SCH-ON");
      mqttClient.subscribe("MQTT-MAIN-ON-OFF-ESP");
      mqttClient.subscribe("MQTT-SCH-ESP-ON");
    }
    else{
      Serial.print("failed");
      Serial.print(mqttClient.state());
      delay(5000);
    }
  }
}

void buzzerOn(bool on){
  if (on){
    tone(BUZZER,256);
  }
  else{
    noTone(BUZZER);
  }
}

void updateTemperature(){
  TempAndHumidity data = dhtSensor.getTempAndHumidity();
  String(data.temperature,2).toCharArray(tempAr,6);
}

void receiveCallback(char* topic, byte* payload, unsigned int length){
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

  char payloadCharAr[length];
  for(int i = 0; i<length; i++){
    Serial.print((char)payload[i]);
    payloadCharAr[i] = (char)payload[i];
  }
  Serial.println();

  // compares if topic is MQTT-ON-OFF. If true returns 0
  if(strcmp(topic,"MQTT-ON-OFF") == 0){
    buzzerOn(payloadCharAr[0] == '1');
  } else if(strcmp(topic,"MQTT-SCH-ON") == 0){
    if(payloadCharAr[0] == 'N'){
      isScheduledON = false;
    } else{
      isScheduledON = true;
      scheduledOnTime = atoi(payloadCharAr);
    }
  }
}

unsigned long getTime(){
  timeClient.update();
  return timeClient.getEpochTime();
}

void checkSchedule(){
  if(isScheduledON){
    unsigned long currentTime = getTime();
    if(currentTime>scheduledOnTime) {
      buzzerOn(true);
      isScheduledON = false;
      mqttClient.publish("MQTT-MAIN-ON-OFF-ESP","1");
      mqttClient.publish("MQTT-SCH-ESP-ON","0");
      Serial.println("Schedule ON");
    }
  }
}