
#pragma once

#include "mqtt/subcriber.hpp"
#include "mqtt/publisher.hpp"

#include "proto/trafficlight_cloud.pb.h"
#include "proto/monitor_info.pb.h"
#include "proto/rs_info.pb.h"


struct traffic_light_config
{
    /* data */
    uint16_t id;
    std::string type;
    std::vector<uint16_t> do_addr;
    std::vector<std::string> color;
};

struct roadside_info_config
{
    std::string id;
    double longitude;
    double latitude;
    double altitude;
    uint32_t isLight;
};


struct traffic_light_status_config
{
    /* data */
    uint16_t id;
    std::string color;
};

struct traffic_mode_config
{
    uint16_t id;
    std::vector<traffic_light_status_config> lights;
};


class TrafficLightControl
{
    using CONTROL_PUBER = std::shared_ptr<mqtt_dataio::publisher<std::vector<uint8_t>>>;
    using CONTROL_SUBER = std::shared_ptr<mqtt_dataio::subscriber<std::vector<uint8_t>>>;

public:
    TrafficLightControl(
        const std::string& traffic_states_topic,
        const std::map<std::string, roadside_info_config>& roadside_info_config_map,
        const std::string& light_control_topic
    );

    ~TrafficLightControl();
    void exec();

private:
    void init();

private:
    bool __m_running;

    const std::string __m_traffic_states_topic;

    std::shared_ptr<mqtt_dataio::publisher<cloud::IntersectionTrafficMode>> __m_traffic_mode_puber;

    // traffic light status feedback thread
    std::shared_ptr<std::thread> __m_resp_thread;
    std::shared_ptr<mqtt_dataio::publisher<fleet::RoadsideInfoList>> __m_roadside_info_puber;
    std::mutex __m_roadside_info_mtx;
    std::map<std::string, fleet::RoadsideInfo> __m_roadsize_info;

    std::map<uint16_t, bool> __m_control_status;

    std::string __m_light_control_topic;
    std::shared_ptr<mqtt_dataio::subscriber<fleet::LightControl>> __m_light_control_suber;

    std::map<std::string, roadside_info_config> __m_roadside_info_map;
    std::map<std::string, CONTROL_PUBER> __m_traffic_control_pubers;
    std::map<std::string, CONTROL_SUBER> __m_traffic_control_subers;


    void on_traffic_light_feedback(const std::vector<uint8_t>& msg);

    std::string cvt_light_status(const fleet::LightStatus &status);
    fleet::LightStatus cvt_light_status(const std::string &status);
};
