#include <atomic>
#include <csignal>
#include <exception>
#include <iostream>
#include <string>

#include "data_processor.hpp"
#include "run_config.hpp"
#include "shm_ring.hpp"

namespace {

constexpr const char* kDefaultConfigPath = "run_config.json";

std::atomic<bool> g_stop_requested{false};

void signal_handler(int /*signal*/) {
    g_stop_requested.store(true, std::memory_order_relaxed);
}

void install_signal_handlers() {
    std::signal(SIGINT, signal_handler);
    std::signal(SIGTERM, signal_handler);
}

[[nodiscard]] auto read_config_path(int argc, char** argv) -> std::string {
    std::string config_path = kDefaultConfigPath;
    for (int index = 1; index < argc; ++index) {
        const std::string arg = argv[index];
        if (arg == "--config" && (index + 1) < argc) {
            config_path = argv[++index];
        }
    }
    return config_path;
}

}  // namespace

int main(int argc, char** argv) {
    install_signal_handlers();

    try {
        const auto config_path = read_config_path(argc, argv);
        const auto config = radar::config::load_run_config(config_path);

        auto preprocessed_ring = radar::ipc::ShmRing::open_or_create(
            config.rings.preprocessed.name,
            config.rings.preprocessed.capacity,
            config.rings.preprocessed.slot_size_bytes
        );
        auto results_ring = radar::ipc::ShmRing::open_or_create(
            config.rings.results.name,
            config.rings.results.capacity,
            config.rings.results.slot_size_bytes
        );

        radar::processing::DataProcessor processor(
            config,
            preprocessed_ring,
            results_ring,
            radar::processing::create_default_processors()
        );
        processor.run(g_stop_requested);
        return 0;
    } catch (const std::exception& exception) {
        std::cerr << "data_processor error: " << exception.what() << '\n';
        return 1;
    }
}
