#include <iostream>
#include <fstream>
#include <sstream>

#include "3th-part/json.hpp"
#include "mqtt/mqtt_client.hpp"
#include "traffic_light_control.hpp"

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "please input config file, such as config.json" << std::endl;
        return 0;
    }

    if(access(argv[1], F_OK) != 0)
    {
        std::cerr << "file not exist: " << argv[1] << std::endl;
        return 0;
    }
    std::ifstream file(argv[1]);
    if (!file)
    {
        std::cerr << "can't open file " << argv[1] << std::endl;
        return 0;
    }

    std::ostringstream ss;
    ss << file.rdbuf();
    std::string content = ss.str();

    if (content.empty())
    {
        std::cout << "config file is empty!" << std::endl;
    }
    else
    {
        try
        {
            nlohmann::json j = nlohmann::json::parse(content);

            // config of mqtt
            std::string ip = j["mqtt_server_ip"];
            uint16_t port = j["mqtt_server_port"];
            std::string user = j["mqtt_server_user"];
            std::string pwd = j["mqtt_server_pwd"];

            // config of traffic light
            std::string light_states_topic = j["light_states_topic"];
            std::string light_control_topic = j["light_control_topic"];
            auto road_config = j["road_id_map_config"];
            std::map<std::string, roadside_info_config> roadside_config;
            for (auto tmp : road_config)
            {
                roadside_info_config info_config{
                                        tmp["id"], 
                                        tmp["longitude"],
                                        tmp["latitude"],
                                        tmp["altitude"],
                                        tmp["isLight"]};
                roadside_config.insert({tmp["id"], info_config});
            }

            mqtt_dataio::client::ins().init(ip, port, user, pwd);

            auto node = std::make_shared<TrafficLightControl>(light_states_topic, roadside_config, light_control_topic);

            node->exec();
        }
        catch (const std::exception &e)
        {
            std::cerr << "catch exception: " << e.what() << '\n';
            return 0;
        }
    }

    return 1;
}
