#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include "DHT.h"
#include <ArduinoJson.h>

// WiFi Setting
const char* ssid = "Wokwi-GUEST";
const char* password = "";

// MQTT Setting
const char* mqttServer = "broker.emqx.io";
const int mqttPort = 1883;
const char* myClientID = "Mawardy20";
const char* ledTopic = "Mawardi/Data/Led";
const char* sensorTopicTemperature = "Mawardi/Data/Temperature";
const char* sensorTopicHumidity = "Mawardi/Data/Humidity";
const char* sensorTopicIntensity = "Mawardi/Data/Intensity";

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

#define LED 2
#define DHTPIN 12
#define DHTTYPE DHT22
#define LDRPIN 33
#define OLED_SDA 21
#define OLED_SCL 22
#define SCREEN_ADDRESS 0x3C

DHT dht(DHTPIN, DHTTYPE);
Adafruit_SSD1306 display(128, 64, &Wire, -1);

unsigned long previousMillis = 0;
const long interval = 2000;

void connect_to_AP(const char* ssid, const char* password);
void reconnect();
void mqtt_publish(const char* topic, float value);
void callback(char* topic, byte* message, unsigned int length);

void setup() {
  Serial.begin(115200);
  pinMode(LED, OUTPUT);

  connect_to_AP(ssid, password);

  mqttClient.setServer(mqttServer, mqttPort);
  mqttClient.setCallback(callback);

  dht.begin();
  Wire.begin(OLED_SDA, OLED_SCL);

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("OLED gagal terhubung!"));
    while (true);
  }
  display.display();
}

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

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    float temperature = dht.readTemperature();
    float humidity = dht.readHumidity();
    int ldrValue = analogRead(LDRPIN);

    if (!isnan(temperature) && !isnan(humidity)) {
      mqtt_publish(sensorTopicTemperature, temperature);
      mqtt_publish(sensorTopicHumidity, humidity);
      mqtt_publish(sensorTopicIntensity, ldrValue);
      Serial.println("Data DHT22 dan LDR berhasil dikirim");
    } else {
      Serial.println("Error membaca data DHT22!");
    }

    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println("Data Sensor Wokwi");
    display.print("Temp: "); display.println(temperature);
    display.print("Humidity: "); display.println(humidity);
    display.print("LDR: "); display.println(ldrValue);
    display.display();
  }
}

void connect_to_AP(const char* ssid, const char* password) {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Connected!");
  Serial.print("IP Device: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!mqttClient.connected()) {
    Serial.print("Menghubungkan ke broker MQTT...");
    if (mqttClient.connect(myClientID)) {
      Serial.println("Terhubung!");
      mqttClient.subscribe(ledTopic);
    } else {
      Serial.print("Gagal, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" coba lagi dalam 2 detik");
      delay(2000);
    }
  }
}

void mqtt_publish(const char* topic, float value) {
  char buffer[16];
  dtostrf(value, 1, 2, buffer);
  mqttClient.publish(topic, buffer);
  Serial.print("Mengirim data ke topik: ");
  Serial.print(topic);
  Serial.print(" -> ");
  Serial.println(buffer);
}

void callback(char* topic, byte* message, unsigned int length) {
  String msg;
  for (int i = 0; i < length; i++) {
    msg += (char)message[i];
  }

  if (String(topic) == "Mawardi/Data/Led") {
    int intMessage = msg.toInt();  // Mengkonversi nilai dari string ke int
    Serial.print("\t Data: ");
    Serial.println(intMessage);
    if (intMessage == 1) {
      digitalWrite(LED, HIGH);
      Serial.println("LED ON");
    } else if (intMessage == 0) {
      digitalWrite(LED, LOW);
      Serial.println("LED OFF");
    }
  }
}