#pragma once

#include "fgc/IControlChannel.h"

#include <atomic>
#include <memory>
#include <mutex>
#include <string>

#include <mqtt/async_client.h>

namespace fgc {

// Real control channel over MQTT (Eclipse Paho C++). Subscribes to the tower's
// target_HDG / ControlCode topics and publishes StatusCode / CamEvent. Topic
// scheme: GGS/FWT/<tower>/...  (see docs/mqtt-api.md). Publishes are QoS 1,
// retained.
//
// Unlike the old MQTTClient it does NOT spin a busy-wait thread; Paho's async
// client delivers callbacks on its own threads.
class MqttControlChannel : public IControlChannel,
                           public virtual mqtt::callback,
                           public virtual mqtt::iaction_listener {
public:
    MqttControlChannel(const std::string& broker_ip, const std::string& tower,
                       const std::string& user, const std::string& password);
    ~MqttControlChannel() override;

    bool connect() override;
    void disconnect() override;
    bool connected() const override;

    void publishStatus(int code) override;
    void publishCamEvent(const CamEvent& event) override;
    ControlCommand poll() override;

private:
    // mqtt::callback
    void connected(const std::string& cause) override;
    void connection_lost(const std::string& cause) override;
    void message_arrived(mqtt::const_message_ptr msg) override;
    // mqtt::iaction_listener
    void on_failure(const mqtt::token& tok) override;
    void on_success(const mqtt::token& tok) override {}

    void publish(const std::string& topic, const std::string& payload);

    std::string           tower_;
    std::string           topic_target_hdg_;
    std::string           topic_control_code_;
    std::string           topic_status_;
    std::string           topic_cam_event_;

    mqtt::async_client     client_;
    mqtt::connect_options  conn_opts_;
    std::atomic<bool>      connected_{false};

    std::mutex             mutex_;
    ControlCommand         sub_data_;
};

}  // namespace fgc
