use std::{thread, time::Duration};

use anyhow::Result;
use gmqtt_client::{Message, MqttClientBuilder, QoS};
use tokio::runtime;
use tracing::info;

const MQTT_BROKER: &str = "tcp://localhost:1883";

fn main() -> Result<()> {
    let filter = tracing_subscriber::EnvFilter::from_default_env();
    tracing_subscriber::fmt().with_env_filter(filter).init();

    let (mqtt_client, mqtt_worker) = MqttClientBuilder::new(MQTT_BROKER)
        .on_connected_callback(on_mqtt_connected)
        .on_message_callback(on_mqtt_message)
        .client_id("example-client")
        .subscribe("client/example/receive", QoS::AtLeastOnce)
        .build()?;

    let worker_runtime = runtime::Builder::new_multi_thread()
        .enable_all()
        .worker_threads(1)
        .build()?;

    worker_runtime.spawn(async { mqtt_worker.run().await });

    let mut counter = 0;

    loop {
        let message = serde_json::json!({ "counter": counter });

        mqtt_client.publish_json(
            "client/example/publish",
            &message,
            false,
            QoS::AtLeastOnce,
            Some(Duration::from_secs(1)),
        )?;

        info!("Example signals published");

        counter += 1;

        thread::sleep(Duration::from_secs(1));
    }
}

fn on_mqtt_connected() {
    info!("MQTT connected");
}

fn on_mqtt_message(message: &Message) {
    println!(
        "MQTT message received: {}",
        String::from_utf8_lossy(message.payload())
    );
}
