#include <WiFi.h> //Import two new library
#include <PubSubClient.h>
#include "DHTesp.h"
#include "Simpletimer.h"
#include <LiquidCrystal_I2C.h>

#define WIFI_SSID "Wokwi-GUEST" //WIFI SSID NAME
#define WIFI_PW "" //WIFI PASSWORD
#define MQTT_BROKER "broker.emqx.io" //MQTT BROKER IP
#define MQTT_PORT 1883 //MQTT BROKER PORT

const int DHT_PIN = 15;
boolean LCDblinkWiFi=true;
boolean LCDblinkMqtt=true;
int pos = 0;
int OnOffAutoInt = 0;

WiFiClient espClient; // ESP8266 Wifi Client
PubSubClient client(espClient); // MQTT Client using the Wifi-Client
DHTesp dhtSensor;
Simpletimer timerDHT{};
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 20, 4);

byte customChar0[] = {
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x1F,
  0x0E,
  0x04
};

byte customChar1[] = {
  0x00,
  0x00,
  0x00,
  0x1F,
  0x00,
  0x0E,
  0x00,
  0x04
};
byte customChar2[] = {
  0x05,
  0x06,
  0x07,
  0x00,
  0x00,
  0x1C,
  0x0C,
  0x14
};
byte customChar3[] = {
  0x01,
  0x0A,
  0x0C,
  0x0E,
  0x0E,
  0x06,
  0x0A,
  0x10
};

void callbackDHT() {
  TempAndHumidity  data = dhtSensor.getTempAndHumidity();
  Serial.println("Temp: " + String(data.temperature, 2) + "°C");
  Serial.println("Humidity: " + String(data.humidity, 2) + "%");  
  LCD.clear();
  LCD.setCursor(0, 0);
  LCD.print("Tem:");
  LCD.print(String(data.temperature, 2));
  LCD.setCursor(0, 1);
  LCD.print("Hum:");
  LCD.print(String(data.humidity, 2));
  LCD.setCursor(0, 2);
  LCD.print("Mode:");
  switch (OnOffAutoInt) {
    case 0:
      LCD.print("Off");
      break;
    case 1:
      LCD.print("Auto");
      break;
    case 2:
      LCD.print("90");
      break;
    case 3:
      LCD.print("180");
      break;
  }
  LCD.setCursor(0, 3);
  LCD.print("Pos:");
  //LCD.print(String(pos, 2));
  client.publish("GM-T", String(data.temperature, 2).c_str());
  client.publish("GM-H", String(data.humidity, 2).c_str());
  if (WiFi.status() == WL_CONNECTED){
    if (LCDblinkWiFi) {
      LCD.setCursor(17, 0);
      LCD.write(0);
    } else {
      LCD.setCursor(17, 0);
      LCD.write(1);
    }
    LCDblinkWiFi = !LCDblinkWiFi;
  } 
  else {
    LCD.setCursor(17, 0);
    LCD.print(".");
  }
  if (client.connected()){
    if (LCDblinkMqtt) {
      LCD.setCursor(18, 0);
      LCD.write(2);
    } else {
      LCD.setCursor(18, 0);
      LCD.write(3);
    }
    LCDblinkMqtt = !LCDblinkMqtt;
  } 
  else {
    LCD.setCursor(17, 0);
    LCD.print(".");
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  String ValueString;
  Serial.print("Message arrived in topic: "); // Print out the topic
  Serial.println(topic);
  Serial.print("Message:"); //Print Received message
  for (int i = 0; i < length; i++) {
    ValueString=ValueString+(char)payload[i];
  }
  //OnOffAutoInt=ValueString.toInt(); 
  Serial.println(ValueString);
  OnOffAutoInt=ValueString.toInt();
  Serial.print("OnOffAutoInt=");
  Serial.println(OnOffAutoInt);
  if (ValueString=="0"){
    LCD.setCursor(0, 2);
    LCD.print("Mode:Off");
    LCD.setCursor(0, 3);
    LCD.print("Pos:0");
  }
  if (ValueString=="1"){
    LCD.setCursor(0, 2);
    LCD.print("Mode:45");
    LCD.setCursor(0, 3);
    LCD.print("Pos:");
  }
  if (ValueString=="2"){
    LCD.setCursor(0, 2);
    LCD.print("Mode:90");
    LCD.setCursor(0, 3);
    LCD.print("Pos:90");
  }
  if (ValueString=="3"){
    LCD.setCursor(0, 2);
    LCD.print("Mode:On");
    LCD.setCursor(0, 3);
    LCD.print("Pos:180");
  }
}

void setup() {

  Serial.begin(115200);
  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
  timerDHT.register_callback(callbackDHT);
  LCD.init();
  LCD.backlight();
  LCD.createChar(0, customChar0);
  LCD.createChar(1, customChar1);
  LCD.createChar(2, customChar2);
  LCD.createChar(3, customChar3);

  WiFi.begin(WIFI_SSID, WIFI_PW); // Start Wi-Fi connection

  while (WiFi.status() != WL_CONNECTED) { // Waiting for connection success
    delay(250);
    Serial.println(".");
  }
  Serial.println("Hello from ESP8266");
  LCD.setCursor(0, 0);
  LCD.print("Connecting to ");
  Serial.print("Connected to hotspot: ");
  Serial.println(WIFI_SSID);
  Serial.print("IP address is: ");
  Serial.println(WiFi.localIP());
  Serial.println("-------------------------");

  client.setCallback(callback);
  client.setServer(MQTT_BROKER, MQTT_PORT); //Start MQTT connection
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESPSENSOR", "Golev08", "Golev11")) { //Sign in to the broker
      Serial.println("Connected to broker");
      client.subscribe("OnOff");
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
}

void loop() {
  timerDHT.run(1000);
  client.loop();
}